예제 #1
0
 public function clean()
 {
     if (!isset($this->themeInfo)) {
         return;
     }
     if (!isset($this->themeInfo->hash)) {
         return;
     }
     // don't clean if in DB because it means someone has posted the archive previously, and maybe the current user tries to erase it.
     if (USE_DB) {
         $history = new History();
         $id = $history->getIdFromHash($this->themeInfo->hash);
         if (!empty($id)) {
             return;
         }
     }
     $zipfilepath = self::hashToPathUpload($this->themeInfo->hash);
     $unzippath = TC_ROOTDIR . '/../themecheck_vault/unzip/' . $this->themeInfo->hash;
     $unzippath_parent = TC_ROOTDIR . '/../themecheck_vault/unzip/' . $this->themeInfo->hash . '_tc_parentzip';
     if (file_exists($zipfilepath)) {
         unlink($zipfilepath);
     }
     if (file_exists($unzippath)) {
         ListDirectoryFiles::recursiveRemoveDir($unzippath);
     }
     if (file_exists($unzippath_parent)) {
         ListDirectoryFiles::recursiveRemoveDir($unzippath_parent);
     }
 }
예제 #2
0
 /**
  *		Analyze an unzipped theme and get metadata
  **/
 public function initFromUnzippedArchive($unzippath, $zipfilename, $zipmimetype, $zipfilesize)
 {
     $this->zipfilename = $zipfilename;
     $this->zipmimetype = $zipmimetype;
     $this->zipfilesize = $zipfilesize;
     $this->userIp = $_SERVER['REMOTE_ADDR'];
     if ($this->userIp == '::1') {
         $this->userIp = '127.0.0.1';
     }
     $this->layout = 0;
     $rawlicense = '';
     // list of meaningful files in themes
     // txt, csv, etc. are meaningless
     $filetypes = array('css' => false, 'php' => false, 'html' => false, 'phtml' => false, 'htm' => false, 'xml' => false, 'gif' => false, 'jpeg' => false, 'png' => false, 'psd' => false, 'ai' => false, 'doc' => false, 'docx' => false, 'rtf' => false);
     try {
         $files = listdir($unzippath);
     } catch (Exception $e) {
         UserMessage::enqueue(__("Cannot list files in archive."), ERRORLEVEL_FATAL);
         return false;
     }
     if (empty($files)) {
         UserMessage::enqueue(__("Cannot list files in archive."), ERRORLEVEL_FATAL);
         return false;
     }
     // test for nested zips
     $nestedzipfiles = array();
     $indexphp_count = 0;
     foreach ($files as $key => $filename) {
         $path_parts = pathinfo($filename);
         if (isset($path_parts['extension'])) {
             if ($path_parts['extension'] == 'zip') {
                 $nestedzipfiles[] = $filename;
             }
             if ($path_parts['basename'] == 'index.php') {
                 /*	$subdir = substr($path_parts['dirname'], strpos($path_parts['dirname'], '/unzip/') + 7);
                 			if (strpos($subdir,"\\")!==false || strpos($subdir,"/")!==false)
                 			{
                 				UserMessage::enqueue(__("index.php must be in root directory."), ERRORLEVEL_FATAL);
                 				return false;
                 			}*/
                 $indexphp_count++;
             }
         }
     }
     if (count($nestedzipfiles) > 0 && $indexphp_count == 0) {
         $curpath = trim($unzippath, "\\/");
         if (strpos($curpath, '_tc_parentzip') !== false) {
             UserMessage::enqueue(__("Multiple level nested zip archives are not supported."), ERRORLEVEL_FATAL);
             return false;
         }
         $newpath = $curpath . '_tc_parentzip';
         if (!file_exists($newpath)) {
             rename($curpath, $newpath);
         }
         if (!file_exists($newpath)) {
             UserMessage::enqueue(__("Nested zip archives are not supported."), ERRORLEVEL_FATAL);
             return false;
         }
         try {
             $zipfilepath = str_replace($curpath, $newpath, $nestedzipfiles[0]);
             $zip = new \ZipArchive();
             $unzippath = $curpath;
             $res = $zip->open($zipfilepath);
             if ($res === TRUE) {
                 if (file_exists($unzippath)) {
                     ListDirectoryFiles::recursiveRemoveDir($unzippath);
                 }
                 // needed to avoid keeping old files that don't exist anymore in the new archive
                 $zip->extractTo($unzippath);
                 $zip->close();
             } else {
                 UserMessage::enqueue(__("File could not be unzipped."), ERRORLEVEL_FATAL);
             }
         } catch (Exception $e) {
             UserMessage::enqueue(__("Archive extraction failed. The following exception occured : ") . $e->getMessage(), ERRORLEVEL_FATAL);
         }
         return $this->initFromUnzippedArchive($unzippath, $zipfilename, $zipmimetype, $zipfilesize);
         // only $unzippath has changed, other values still refer to parent zip
     }
     $this->themetype = $this->detectThemetype($unzippath);
     $merchant = self::getMerchant($unzippath, $this);
     $this->isThemeForest = $merchant == 'themeforest' ? true : false;
     $this->isTemplateMonster = $merchant == 'templatemonster' ? true : false;
     $this->namedemo = '';
     // undefined theme type
     if ($this->themetype == TT_UNDEFINED) {
         UserMessage::enqueue(__("Archive is not a valid theme file."), ERRORLEVEL_FATAL);
         return false;
     }
     if ($this->themetype == TT_WORDPRESS || $this->themetype == TT_WORDPRESS_CHILD) {
         $style_css = null;
         // loop through files to find style.css (at root level since there can be other style.css files in subdirs)
         foreach ($files as $key => $filename) {
             $path_parts = pathinfo($filename);
             $basename = $path_parts['basename'];
             if ($basename == 'style.css') {
                 if (empty($style_css)) {
                     $style_css = $filename;
                     $this->themeroot = realpath($path_parts['dirname']);
                     $explod = explode(DIRECTORY_SEPARATOR, $this->themeroot);
                     if (count($explod) > 0) {
                         $this->namedemo = $explod[count($explod) - 1];
                     }
                 } else {
                     if (strlen($filename) < strlen($style_css)) {
                         $style_css = $filename;
                         $this->themeroot = realpath($path_parts['dirname']);
                         $explod = explode(DIRECTORY_SEPARATOR, $this->themeroot);
                         if (count($explod) > 0) {
                             $this->namedemo = $explod[count($explod) - 1];
                         }
                     }
                 }
             }
             if (isset($path_parts['extension'])) {
                 $ext = strtolower(trim($path_parts['extension']));
                 if (isset($filetypes[$ext])) {
                     $filetypes[$ext] = true;
                 }
             }
         }
         if (empty($style_css)) {
             UserMessage::enqueue(__("style.css is missing or misspelled."), ERRORLEVEL_FATAL);
             return false;
         } else {
             $file_content = file_get_contents($style_css);
             if (preg_match('/[ \\t\\/*#]*Theme Name:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->name = trim($match[1]);
             } else {
                 UserMessage::enqueue(__("style.css does not contain Theme name. Theme name is mandatory."), ERRORLEVEL_FATAL);
                 return false;
             }
             if (preg_match('/[ \\t\\/*#]*Description:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->descriptionBB = trim(strip_tags(Helpers::encodeBB($match[1])));
                 $this->description = Helpers::decodeBB($this->descriptionBB);
             }
             if (preg_match('/[ \\t\\/*#]*Author:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->author = trim($match[1]);
             }
             if (preg_match('/[ \\t\\/*#]*Theme URI:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->themeUri = trim($match[1]);
             }
             if (preg_match('/[ \\t\\/*#]*Author URI:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->authorUri = trim($match[1]);
             }
             if (preg_match('/[ \\t\\/*#]*Version:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->version = trim($match[1]);
             }
             if (preg_match('/[ \\t\\/*#]*License:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $rawlicense = trim($match[1]);
             }
             if (preg_match('%[ \\t\\/*#]*License URI:.*(https?://[A-Za-z0-9-\\./_~:?#@!$&\'()*+,;=]*)%mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->licenseUri = trim($match[1]);
             }
             if (preg_match('/[ \\t\\/*#]*Tags:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->tags = trim($match[1]);
                 // layout
                 if (strpos($this->tags, 'fixed-layout') !== false) {
                     $this->layout = 1;
                 }
                 if (strpos($this->tags, 'fluid-layout') !== false) {
                     $this->layout = 2;
                 }
                 if (strpos($this->tags, 'responsive-layout') !== false) {
                     $this->layout = 3;
                 }
             }
             if ($this->themetype == TT_WORDPRESS_CHILD && preg_match('/[ \\t\\/*#]*Template:(.*)$/mi', $file_content, $match) && !empty($match) && count($match) == 2) {
                 $this->parentName = trim($match[1]);
             }
             // creation date can come from an external source. Happens with massimport where creation date is in csv files.
             global $g_creationDate;
             $this->creationDate = $g_creationDate;
         }
         $this->cmsVersion = "3.9.1";
     }
     if ($this->themetype == TT_JOOMLA) {
         foreach ($files as $key => $filename) {
             $path_parts = pathinfo($filename);
             $basename = $path_parts['basename'];
             if ($basename == 'templateDetails.xml') {
                 libxml_use_internal_errors(true);
                 $xml = simplexml_load_file($filename);
                 if (count(libxml_get_errors()) > 0) {
                     foreach (libxml_get_errors() as $error) {
                         $message = __("Malformed xml file templateDetails.xml. Cannot continue. Error details : ");
                         $message .= $error->message;
                         UserMessage::enqueue($message, ERRORLEVEL_FATAL);
                     }
                     return false;
                     libxml_clear_errors();
                 }
                 if (empty($xml)) {
                     UserMessage::enqueue(__("templateDetails.xml is empty or contains malformed xml"), ERRORLEVEL_FATAL);
                     return false;
                 }
                 if ($xml->getName() == 'extension' || $xml->getName() == 'install' || $xml->getName() == 'mosinstall') {
                     if (!empty($xml->name)) {
                         $this->name = (string) $xml->name;
                     } else {
                         UserMessage::enqueue(__("templateDetails.xml does not have a name tag. name is mandatory."), ERRORLEVEL_FATAL);
                         return false;
                     }
                     if (!empty($xml->description)) {
                         $this->descriptionBB = trim(strip_tags(Helpers::encodeBB((string) $xml->description)));
                         $this->description = Helpers::decodeBB($this->descriptionBB);
                     }
                     if (!empty($xml->author)) {
                         $this->author = (string) $xml->author;
                     }
                     if (!empty($xml->authorUrl)) {
                         $this->authorUri = (string) $xml->authorUri;
                     }
                     if (!empty($xml->authorMail)) {
                         $this->authorUri = (string) $xml->authorMail;
                     }
                     if (!empty($xml->version)) {
                         $this->version = (string) $xml->version;
                     }
                     if (!empty($xml->copyright)) {
                         $this->copyright = (string) $xml->copyright;
                     }
                     if (!empty($xml->creationDate)) {
                         $this->creationDate = strtotime((string) $xml->creationDate);
                     }
                     if (empty($this->creationDate)) {
                         // creation date can come from an external source. Happens with massimport where creation date is in csv files.
                         global $g_creationDate;
                         $this->creationDate = $g_creationDate;
                     }
                     if (!empty($xml->license)) {
                         $rawlicense = (string) $xml->license;
                     }
                     if ($xml->getName() == 'extension') {
                         $attrs = $xml->attributes();
                         if (isset($attrs["version"])) {
                             $this->cmsVersion = (string) $attrs["version"];
                         } else {
                             $this->cmsVersion = "3.0+";
                         }
                     }
                     if ($xml->getName() == 'install') {
                         $attrs = $xml->attributes();
                         if (isset($attrs["version"])) {
                             $this->cmsVersion = (string) $attrs["version"];
                         } else {
                             $this->cmsVersion = "1.5";
                         }
                     }
                     if ($xml->getName() == 'mosinstall') {
                         $this->cmsVersion = "1.0";
                     }
                     // layout
                     if (!empty($this->description)) {
                         if (stripos($this->description, 'fluid') !== false) {
                             $this->layout = 2;
                         }
                         if (stripos($this->description, 'responsive') !== false) {
                             $this->layout = 3;
                         }
                     }
                 } else {
                     UserMessage::enqueue(__("templateDetails.xml does not have a mosinstall, extension or install or node"), ERRORLEVEL_FATAL);
                     return false;
                 }
                 $this->themeroot = realpath($path_parts['dirname']);
             }
             if (isset($path_parts['extension'])) {
                 $ext = strtolower(trim($path_parts['extension']));
                 if (isset($filetypes[$ext])) {
                     $filetypes[$ext] = true;
                 }
             }
         }
         if (empty($this->name)) {
             UserMessage::enqueue(___("templateDetails.xml is emissing or misspelled."), ERRORLEVEL_FATAL);
             return false;
         }
         // for joomla, extract namedemo from zip name
         $zipfilename_exploded = explode('.', $this->zipfilename);
         array_pop($zipfilename_exploded);
         $this->namedemo = implode('.', $zipfilename_exploded);
     }
     $this->modificationDate = time();
     $this->validationDate = time();
     $this->license = self::getLicense($rawlicense);
     if (preg_match('%(https?://[A-Za-z0-9-\\./_~:?#@!$&\'()*+,;=])%i', $rawlicense, $match) && !empty($match) && count($match) == 2) {
         $this->licenseUri = trim($match[1]);
     }
     if (empty($this->licenseUri)) {
         $this->licenseUri = self::getLicenseUri($this->license);
     }
     if ($this->license == TC_LICENSE_CUSTOM) {
         $this->licenseText = $rawlicense;
     }
     $this->hasBacklinKey = false;
     if ($filetypes['css']) {
         $this->filesIncluded .= 'CSS, ';
     }
     if ($filetypes['php']) {
         $this->filesIncluded .= 'PHP, ';
     }
     if ($filetypes['html'] || $filetypes['phtml'] || $filetypes['htm']) {
         $this->filesIncluded .= 'HTML, ';
     }
     if ($filetypes['xml']) {
         $this->filesIncluded .= 'XML, ';
     }
     if ($filetypes['gif'] || $filetypes['jpeg'] || $filetypes['png']) {
         $this->filesIncluded .= 'Bitmap images, ';
     }
     if ($filetypes['psd']) {
         $this->filesIncluded .= 'Adobe Photoshop, ';
     }
     if ($filetypes['xml']) {
         $this->filesIncluded .= 'Adobe Illustrator, ';
     }
     if ($filetypes['doc'] || $filetypes['docx']) {
         $this->filesIncluded .= 'MS Word, ';
     }
     if ($filetypes['rtf']) {
         $this->filesIncluded .= 'RTF, ';
     }
     $this->filesIncluded = trim($this->filesIncluded, " ,");
     // get themeforest url
     if ($this->isThemeForest) {
         preg_match('/[ 0-9a-zA-Z_-]+/', $this->name, $matches, PREG_OFFSET_CAPTURE);
         $search = trim($matches[0][0]);
         $url = 'http://marketplace.envato.com/api/edge/search:themeforest,wordpress,' . $search . '.json';
         $ch = curl_init();
         curl_setopt($ch, CURLOPT_URL, $url);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
         $result = curl_exec($ch);
         curl_close($ch);
         $result = json_decode($result);
         if (!empty($result) && !empty($result->search)) {
             $this->themeUri = $result->search[0]->url;
         }
     }
     return true;
 }