public function testFromFileName()
 {
     $this->assertEquals(CopixMIMETypes::getFromFileName('c:\\mon\\fichier/avec/un/truc long/et des accents é/myFile.txt'), 'text/plain');
     $this->assertEquals(CopixMIMETypes::getFromFileName('c:\\mon\\fichier.files/avec/un/truc long/et des accents é/myFile.txt'), 'text/plain');
     $this->assertEquals(CopixMIMETypes::getFromFileName('c:\\mon\\fichier.files/avec/un/truc long/et des accents é/myFile'), 'application/octet-stream');
     $this->assertEquals(CopixMIMETypes::getFromFileName('/avec/un/truc long/et des accents é/myFile.xls'), 'application/vnd.ms-excel');
 }
 /**
  * Recupère la ressource
  *
  * @throws CopixResourceForbiddenException si l'accès à la ressource est interdit,
  *         CopixResourceNotFoundException si la ressource n'a pas été trouvée.
  */
 public function fetch()
 {
     // Vérifie qu'on ait pas de "backward"
     $unescapedPath = utf8_decode($this->_path);
     // Pas de blague avec l'UTF8
     if (preg_match('@\\.\\.[/\\\\]@', $unescapedPath)) {
         throw new CopixResourceForbiddenException($this->_path);
     }
     // Vérifie l'existence du theme
     if (!$this->_theme || !is_dir('themes/' . $this->_theme)) {
         throw new CopixResourceNotFoundException($this->_theme);
     }
     $arModules = $this->_getArModules();
     // Si on a bien un module
     if ($this->_module) {
         // Vérifie l'existence du module
         if (isset($arModules[$this->_module])) {
             $this->_modulePath = $arModules[$this->_module] . $this->_module . '/';
         } else {
             throw new CopixResourceNotFoundException($this->_module);
         }
         // Vérifie l'existence du chemin 'www' du module
         if (!is_dir($this->_modulePath . "www")) {
             throw new CopixResourceNotFoundException($this->_module);
         }
     }
     // Récupère la config
     $config = $this->_getCopixConfig();
     // Recherche le fichier
     if (!($filePath = CopixResource::findResourcePath($this->_path, $this->_module, $this->_modulePath, $this->_theme, $config->i18n_path_enabled, $this->_lang, $this->_country))) {
         throw new CopixResourceNotFoundException($this->_path);
     }
     // Récupère le type MIME
     $mimeType = CopixMIMETypes::getFromFileName($filePath);
     // La substitution ne touche que les fichiers des modules
     if ($this->_modulePath && substr($filePath, 0, strlen($this->_modulePath)) == $this->_modulePath) {
         $filePath = $this->_processModuleFile($filePath, $mimeType);
     }
     // Mode DEBUG ?
     if (isset($_REQUEST['DEBUG'])) {
         _dump(array('this' => $this, 'filePath' => $filePath, 'mimeType' => $mimeType, 'included_files' => get_included_files()));
         exit;
     }
     // Envoie le fichier
     $this->_sendFile($filePath, $mimeType);
 }
 /**
  * Lancement d'une requête
  *
  * @param CopixHTTPClientRequest $pRequest
  * @return unknown
  */
 private function _launchRequest(CopixHTTPClientRequest $pRequest)
 {
     if (CopixConfig::get('default|proxyEnabled')) {
         //proxy_host, proxy_port, proxy_login  et proxy_password
         curl_setopt($this->_curl, CURLOPT_HTTPPROXYTUNNEL, true);
         if (CopixConfig::get('default|proxyHost') != null) {
             curl_setopt($this->_curl, CURLOPT_PROXY, str_replace('http://', '', CopixConfig::get('default|proxyHost')));
         }
         if (CopixConfig::get('default|proxyPort') != null) {
             curl_setopt($this->_curl, CURLOPT_PROXYPORT, intval(CopixConfig::get('default|proxyPort')));
         }
         if (CopixConfig::get('default|proxyUser') != null) {
             $proxyUserPass = CopixConfig::get('default|proxyUser');
             if (CopixConfig::get('default|proxyPass') != null) {
                 $proxyUserPass .= ':' . CopixConfig::get('default|proxyPass');
             }
             curl_setopt($this->_curl, CURLOPT_PROXYUSERPWD, $proxyUserPass);
         }
     }
     curl_setopt($this->_curl, CURLOPT_TIMEOUT, $pRequest->getTimeout());
     // Choix de l'interface à utiliser
     $interfaceUsed = $pRequest->getInterface();
     // Si pas d'interface on récupère celle en configuration
     if ($interfaceUsed !== '') {
         $interfaceUsed = CopixConfig::get('default|webservicesInterface');
     }
     // Mise en place de l'interface
     if (isset($interfaceUsed)) {
         curl_setopt($this->_curl, CURLOPT_INTERFACE, $interfaceUsed);
     }
     if ($pRequest->getIgnoreCertificate()) {
         curl_setopt($this->_curl, CURLOPT_SSL_VERIFYPEER, false);
         curl_setopt($this->_curl, CURLOPT_SSL_VERIFYHOST, false);
     }
     curl_setopt($this->_curl, CURLOPT_URL, $pRequest->getUrl());
     curl_setopt($this->_curl, CURLOPT_VERBOSE, 1);
     if ($pRequest->getHeader()) {
         curl_setopt($this->_curl, CURLOPT_HTTPHEADER, $pRequest->getHeader());
     }
     if ($pRequest->getCookie()) {
         curl_setopt($this->_curl, CURLOPT_COOKIE, $pRequest->getCookie());
     }
     if (count($pRequest->getPost())) {
         if ($pRequest->getFile()) {
             $boundary = uniqid('------------------');
             $MPboundary = '--' . $boundary;
             $endMPboundary = $MPboundary . '--';
             $postBody = 'Content-type: multipart/form-data, boundary=' . $boundary . "\r\n\r\n";
             foreach ($pRequest->getPost() as $name => $content) {
                 $postBody .= $MPboundary . "\r\n";
                 $postBody .= 'content-disposition: form-data; name="' . $name . '"' . "\r\n\r\n";
                 $postBody .= $content . "\r\n";
             }
             $file = $pRequest->getFile();
             $fileContent = file_get_contents($file);
             $postBody .= $MPboundary . "\r\n";
             $postBody .= 'Content-Disposition: form-data; name="file"; filename="' . basename($file) . '"' . "\r\n";
             $postBody .= 'Content-Type: ' . CopixMIMETypes::getFromFileName($file) . "\r\n";
             $postBody .= 'Content-Transfer-Encoding: binary' . "\r\n\r\n";
             $postBody .= $fileContent;
             $postBody .= "\r\n" . $endMPboundary;
             curl_setopt($this->_curl, CURLOPT_POST, true);
             curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $postBody);
             curl_setopt($this->_curl, CURLOPT_HTTPHEADER, array("Content-Type: multipart/form-data; boundary={$boundary}"));
             curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true);
         } else {
             curl_setopt($this->_curl, CURLOPT_POST, true);
             curl_setopt($this->_curl, CURLOPT_POSTFIELDS, CopixUrl::valueToUrl(null, $pRequest->getPost()));
         }
     }
     if ($pRequest->getFollowRedirect()) {
         curl_setopt($this->_curl, CURLOPT_FOLLOWLOCATION, 1);
     } else {
         curl_setopt($this->_curl, CURLOPT_FOLLOWLOCATION, 0);
     }
     return new CopixHTTPRequestResult($pRequest, $this->_curl);
 }
 /**
  * Réalise les derniers traitements (généralement d'affichage ou de redirection).
  *
  * En fonction du code retour de l'action CopixActionReturn::CONST, Copix réalise
  * un certain nombre de traitements pour terminer la requête en cours.
  *
  * @param	CopixActionReturn      $pToProcess   Ce qui a été retourné par CopixActionGroup::process ()
  * @see CopixActionGroup
  */
 protected function _processResult($toProcess)
 {
     $config = CopixConfig::instance();
     //appel les plugins de post-processing.
     foreach (CopixPluginRegistry::getRegistered() as $name => $plugin) {
         $plugin->afterProcess($toProcess);
     }
     //Analyse du résultat du process
     switch ($toProcess->code) {
         case CopixActionReturn::ERROR:
             //erreur
             header("Content-Type: text/html");
             $tpl = new CopixTpl();
             if (($assignedTitlePage = $tpl->getAssigned('TITLE_PAGE')) !== null) {
                 $tpl->assign('TITLE_PAGE', '[' . _i18n('copix:common.messages.error') . ']' . $assignedTitlePage);
             } else {
                 $tpl->assign('TITLE_PAGE', '[' . _i18n('copix:common.messages.error') . ']');
             }
             $this->_processStandard($tpl);
             $tpl->assign('HTML_HEAD', '<$HTML_HEAD />');
             $tpl->assign('MAIN', $toProcess->data);
             $content = $tpl->fetch('|error.tpl');
             CopixContext::clear();
             $this->_beforeDisplay($content);
             echo $content;
             break;
         case CopixActionReturn::DISPLAY:
             $charset = CopixI18N::getCharset();
             header("Content-Type: text/html;charset=" . $charset);
             $this->_processStandard($toProcess->data);
             //appel de la méthode de préparation de la page standard.
             $toProcess->data->assign('HTML_HEAD', '<$HTML_HEAD />');
             //Par ex, bandeaux de pub, menus dynamiques, ... (propres aux projets.)
             CopixContext::clear();
             $content = $toProcess->data->fetch($config->mainTemplate);
             $this->_beforeDisplay($content);
             echo $content;
             break;
         case CopixActionReturn::DISPLAY_IN:
             $charset = CopixI18N::getCharset();
             header("Content-Type: text/html;charset=" . $charset);
             $this->_processStandard($toProcess->data);
             //appel de la méthode de préparation de la page standard.
             $toProcess->data->assign('HTML_HEAD', '<$HTML_HEAD />');
             //Par ex, bandeaux de pub, menus dynamiques, ... (propres aux projets.)
             $content = $toProcess->data->fetch($toProcess->more);
             $this->_beforeDisplay($content);
             echo $content;
             break;
         case CopixActionReturn::FILE:
         case CopixActionReturn::CONTENT:
             $contentDisposition = 'inline';
             $contentTransfertEnconding = 'binary';
             $contentType = null;
             $fileNameOnly = null;
             if ($toProcess->code == CopixActionReturn::FILE) {
                 $fileName = $toProcess->data;
                 $fileNameOnly = explode('/', str_replace('\\', '/', $fileName));
                 $fileNameOnly = $fileNameOnly[count($fileNameOnly) - 1];
             }
             if (is_array($toProcess->more)) {
                 if (isset($toProcess->more['content-disposition'])) {
                     $contentDisposition = $toProcess->more['content-disposition'];
                 }
                 if (isset($toProcess->more['filename'])) {
                     $fileNameOnly = $toProcess->more['filename'];
                 }
                 if (isset($toProcess->more['content-type'])) {
                     $contentType = $toProcess->more['content-type'];
                 }
                 if (isset($toProcess->more['content-transfer-encoding'])) {
                     $contentTransfertEnconding = $toProcess->more['content-transfer-encoding'];
                 }
             } elseif (strlen(trim($toProcess->more))) {
                 $contentType = $toProcess->more;
             }
             if ($contentType === null) {
                 $contentType = CopixMIMETypes::getFromFileName($fileNameOnly);
             }
             header("Pragma: public");
             header("Expires: 0");
             header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
             header("Cache-Control: protected", false);
             header("Content-Type: " . $contentType);
             header("Content-Disposition: " . $contentDisposition . "; filename=\"" . $fileNameOnly . "\";");
             header("Content-Transfer-Encoding: " . $contentTransfertEnconding);
             header("Content-Length: " . ($toProcess->code == CopixActionReturn::FILE ? filesize($fileName) : strlen($toProcess->data)));
             if ($toProcess->code == CopixActionReturn::FILE) {
                 readfile($fileName);
             } else {
                 echo $toProcess->data;
             }
             flush();
             break;
         case CopixActionReturn::PPO:
             $contentType = 'text/html';
             $cacheControl = false;
             $mainTemplate = $config->mainTemplate;
             $charset = CopixI18N::getCharset();
             if (is_array($toProcess->more)) {
                 $template = $toProcess->more['template'];
                 if (isset($toProcess->more['content-type'])) {
                     $contentType = $toProcess->more['content-type'];
                 }
                 if (array_key_exists('mainTemplate', $toProcess->more)) {
                     $mainTemplate = $toProcess->more['mainTemplate'];
                 }
                 if (isset($toProcess->more['charset'])) {
                     $charset = $toProcess->more['charset'];
                 }
                 if (isset($toProcess->more['cache-control'])) {
                     $cacheControl = $toProcess->more['cache-control'];
                 }
             } else {
                 $template = $toProcess->more;
             }
             $tplContent = new CopixTpl();
             $tplContent->assign('ppo', $toProcess->data);
             header("Content-Type: " . $contentType . ";charset=" . $charset);
             if ($cacheControl !== false) {
                 header('Cache-Control: ' . $cacheControl);
             }
             if ($mainTemplate !== null) {
                 $tplMain = new CopixTpl();
                 $tplMain->assign('TITLE_PAGE', isset($toProcess->data->TITLE_PAGE) ? $toProcess->data->TITLE_PAGE : null);
                 $tplMain->assign('TITLE_BAR', isset($toProcess->data->TITLE_BAR) ? $toProcess->data->TITLE_BAR : null);
                 $tplMain->assign('POPUP', isset($toProcess->data->POPUP) ? $toProcess->data->POPUP : null);
                 $tplMain->assign('MENU', isset($toProcess->data->MENU) ? $toProcess->data->MENU : null);
                 $tplMain->assign('CAN_CLOSE', isset($toProcess->data->CAN_CLOSE) ? $toProcess->data->CAN_CLOSE : null);
                 $tplMain->assign('BODY_ON_LOAD', isset($toProcess->data->BODY_ON_LOAD) ? $toProcess->data->BODY_ON_LOAD : null);
                 $tplMain->assign('BODY_ON_UNLOAD', isset($toProcess->data->BODY_ON_UNLOAD) ? $toProcess->data->BODY_ON_UNLOAD : null);
                 $tplMain->assign('MAIN', $tplContent->fetch($template));
                 $tplContent = null;
                 //on libère la mémoire
                 $tplMain->assign('ppo', $toProcess->data);
                 $this->_processStandard($tplMain);
                 $tplMain->assign('HTML_HEAD', '<$HTML_HEAD />');
                 $content = $tplMain->fetch($mainTemplate);
             } else {
                 $tplContent->assign('TITLE_PAGE', isset($toProcess->data->TITLE_PAGE) ? $toProcess->data->TITLE_PAGE : null);
                 $tplContent->assign('TITLE_BAR', isset($toProcess->data->TITLE_BAR) ? $toProcess->data->TITLE_BAR : null);
                 $tplContent->assign('BODY_ON_LOAD', isset($toProcess->data->BODY_ON_LOAD) ? $toProcess->data->BODY_ON_LOAD : null);
                 $tplContent->assign('BODY_ON_UNLOAD', isset($toProcess->data->BODY_ON_UNLOAD) ? $toProcess->data->BODY_ON_UNLOAD : null);
                 $this->_processStandard($tplContent);
                 $tplContent->assign('HTML_HEAD', '<$HTML_HEAD />');
                 $content = $tplContent->fetch($template);
             }
             CopixContext::clear();
             $this->_beforeDisplay($content);
             echo $content;
             break;
         case CopixActionReturn::REDIRECT:
             //redirection standard, message http.
             header('location: ' . $toProcess->data);
             break;
         case CopixActionReturn::HTTPCODE:
             foreach ($toProcess->data as $code) {
                 header($code);
             }
             echo $toProcess->more;
             break;
         case CopixActionReturn::NONE:
             break;
     }
     //Appel des méthodes afterDisplay des plugins
     foreach (CopixPluginRegistry::getRegistered() as $name => $plugin) {
         $plugin->afterDisplay();
     }
     session_write_close();
 }