ObjectContainer(); $this->setDSN(DSN); $this->setTableName(SHP_TABLE); $this->setColumnName('SelfHostedPluginID','SelfHostedPluginID'); $this->setColumnName('SelfHostedPluginName','SelfHostedPluginName'); $this->setColumnName('SelfHostedPluginSlug','SelfHostedPluginSlug'); $this->setColumnName('SelfHostedPluginVersions','SelfHostedPluginVersions'); $this->setColumnName('SelfHostedPluginDownloads','SelfHostedPluginDownloads'); $this->setColumnName('SelfHostedPluginRatings','SelfHostedPluginRatings'); $this->setColumnName('SelfHostedPluginRating','SelfHostedPluginRating'); $this->setColumnName('SelfHostedPluginModifiedTimestamp','SelfHostedPluginModifiedTimestamp'); if (!$this->tableExists()){ $this->initializeTable(); } } function initializeTable(){ $this->ensureTableExists(); } function ensureTableExists(){ $create_query=" CREATE TABLE `".$this->getTableName()."` ( `SelfHostedPluginID` int(6) unsigned AUTO_INCREMENT NOT NULL, `SelfHostedPluginName` varchar(255), `SelfHostedPluginSlug` varchar(255), `SelfHostedPluginVersions` text, `SelfHostedPluginDownloads` int(10) unsigned default 0, `SelfHostedPluginRatings` int(10) unsigned default 0, `SelfHostedPluginRating` int(3) unsigned default 0, `SelfHostedPluginModifiedTimestamp` timestamp default NOW(), PRIMARY KEY (`SelfHostedPluginID`), KEY (`SelfHostedPluginName`), KEY (`SelfHostedPluginSlug`) ) TYPE=MyISAM "; if ($this->tableExists()){ return true; } else{ $result = $this->createTable($create_query); if (PEAR::isError($result)){ return $result; } else{ return true; } } } function addUploadedPluginFile($FileWidget,& $SelfHostedPlugin){ if (!is_uploaded_file($_FILES[$FileWidget]['tmp_name'])){ return PEAR::raiseError("There was no uploaded file entered in the file widget $FileWidget"); } // Here goes the fancy stuff. We need to extract the information about the plugin from the uploaded file $Dest = SHP_DIR.'___tmp___.zip'; if (!move_uploaded_file($_FILES[$FileWidget]['tmp_name'],$Dest)){ return PEAR::raiseError("Unable to move ".$_FILES[$FileWidget]['tmp_name']." to $Dest"); } $result = $this->processPluginArchive($Dest,$SelfHostedPlugin); if (PEAR::isError($result)){ return $result; } $plugin_info = $SelfHostedPlugin->getParameter('SelfHostedPluginInfo'); // gets set in processPluginArchive if (!isset($plugin_info['stable_tag'])){ return PEAR::raiseError(sprintf("You must have a Stable tag in the readme.txt file. For more information see the %ssample readme file%s and the %sreadme validator%s",'','','','')); } $filename = basename($_FILES[$FileWidget]['name']); $FinalDestFilename = $SelfHostedPlugin->getParameter('SelfHostedPluginSlug').$plugin_info['stable_tag'].'.zip'; $versions = $SelfHostedPlugin->getVersions(); $versions[$plugin_info['stable_tag']] = array('filename' => $FinalDestFilename,'date' => date("Y-m-d H:i:s")); krsort($versions); $wc = new whereClause(); $wc->addCondition($this->getColumnName('SelfHostedPluginSlug').' = ?',$SelfHostedPlugin->getParameter('SelfHostedPluginSlug')); $wc->addCondition($this->getColumnName('SelfHostedPluginID').' <> ?',$SelfHostedPlugin->getParameter('SelfHostedPluginID')); if ($this->getAllSelfHostedPlugins($wc)){ return PEAR::raiseError('A plugin with the slug `'.$SelfHostedPlugin->getParameter('SelfHostedPluginSlug').'` already exists. There cannot be duplicates.'); } $SelfHostedPlugin->setVersions($versions); if (file_exists(SHP_DIR.$FinalDestFilename)){ unlink(SHP_DIR.$FinalDestFilename); } rename($Dest,SHP_DIR.$FinalDestFilename); if ($SelfHostedPlugin->getParameter('SelfHostedPluginID') == ""){ // Adding it $result = $this->addSelfHostedPlugin($SelfHostedPlugin); } else{ $result = $this->updateSelfHostedPlugin($SelfHostedPlugin); } return $result; } function processPluginArchive($PluginZip,&$SelfHostedPlugin){ // Okay, here's where the meat of the processing happens. // Three things: // 1. A directory called __plugin-updates is added, containing only the file plugin-update-checker.class.php // 2. Some code is inserted at the end of your main plugin file to instantiate the above class // 3. All instances of the file .DS_STORE are removed (what can I say, I develop on a Mac and that file just bugs me) // Also, we parse the ReadMe file and add the info back into the SelfHostedPlugin object // Here we go. First, we'll create a ZipArchive object $zip = new ZipArchive; if ($zip->open($PluginZip,ZIPARCHIVE::CREATE || ZIPARCHIVE::OVERWRITE) === true){ $root = $zip->getNameIndex(0); $SelfHostedPlugin->setParameter('SelfHostedPluginSlug',str_replace('/','',$root)); // slug is taken from the root local directory - the first item in the zip $plugin_info = $this->parseReadme($PluginZip); if (PEAR::isError($plugin_info)){ return $plugin_info; } $SelfHostedPlugin->setParameter('SelfHostedPluginInfo',$plugin_info); $SelfHostedPlugin->setParameter('SelfHostedPluginName',$plugin_info['name']); } else{ return PEAR::raiseError('Unable to process plugin archive file'); } // 1. insert the directory $status = $zip->statName($root.'__plugin-updates/'); if (is_array($status)){ // It already exists, we'll remove it to re-add $zip->deleteName($root.'__plugin-updates/'); } if (!$zip->addEmptyDir($root.'__plugin-updates/')){ return PEAR::raiseError('Unable to add the directory __plugin-updates to the plugin archive'); } if (!$zip->addFile(dirname(__FILE__).'/lib/__plugin-updates/plugin-update-checker.class.php',$root.'__plugin-updates/plugin-update-checker.class.php')){ return PEAR::raiseError('Unable to add the class file plugin-update-checker.class.php to the plugin archive'); } // 2. Insert some code into the main plugin file // First, we have to __find__ the main plugin file $plugin_data_file_found = false; $begin_string = ''; for($i = 0; $i < $zip->numFiles; $i++){ $test = $zip->getNameIndex($i); if (dirname($test).'/' == $root and strpos(basename($test),'.php')){ // good candidate, need to extract it to test it $__tmp_filename = SHP_DIR.'___tmp___.php'; file_put_contents($__tmp_filename,$zip->getFromIndex($i)); $plugin_data = get_plugin_data($__tmp_filename,$markup); if ($plugin_data['Name'] != '' and $plugin_data['Version'] != ''){ // Great, found it. Now, we'll add our code in at the bottom, if it's not already there $plugin_data_file_found = true; $content = file_get_contents($__tmp_filename); if ($begin = strpos($content,$begin_string)){ // It's already in there, remove it (to ensure that we always insert the latest version) $end = strpos($content,$end_string)+strlen($end_string); $content = substr($content,0,$begin).substr($content,$end); } // Great, ready to add it $updateCode = ' /********************************************** * The following was added by Self Hosted Plugin * to enable automatic updates * See http://wordpress.org/extend/plugins/self-hosted-plugins **********************************************/ require "__plugin-updates/plugin-update-checker.class.php"; $__UpdateChecker = new PluginUpdateChecker(\''.get_bloginfo('wpurl').'/'.SHP_REDIRECT_DIR.$SelfHostedPlugin->getParameter('SelfHostedPluginSlug').'/update\', __FILE__,\''.$SelfHostedPlugin->getParameter('SelfHostedPluginSlug').'\'); '; file_put_contents($__tmp_filename,$content.$begin_string.$updateCode.$end_string); // Now, delete the entry in the zip $zip->deleteIndex($i); // And add in our updated file $zip->addFile($__tmp_filename,$test); break; } } } if (!$plugin_data_file_found){ return PEAR::raiseError('Unable to find any .php file with plugin header information. See the File Header Reference'); } // 3. Finally, delete those pesky .DS_Store files $remove_globally = apply_filters('shp_remove_files_from_zip',array('.DS_Store')); // Allow plugins to augment for($i = 0; $i < $zip->numFiles; $i++){ if (in_array(basename($zip->getNameIndex($i)),$remove_globally)){ $zip->deleteIndex($i); } } // All done. if (!$zip->close()){ return PEAR::raiseError('Unable to make required updates to the plugin'); } if (file_exists($__tmp_filename)){ unlink($__tmp_filename); } return true; } function parseReadme($PluginZip){ $zip = new ZipArchive; if ($zip->open($PluginZip) === true){ $root = $zip->getNameIndex(0); $readme = $zip->getFromName($root.'readme.txt'); $zip->close(); if (!$readme){ return PEAR::raiseError("You must have a valid WordPress readme.txt file within the plugin zip"); } include_once('lib/parse-readme/parse-readme.php'); $Automattic_Readme = new Automattic_Readme(); $plugin_info = $Automattic_Readme->parse_readme_contents($readme); if (!$plugin_info){ return PEAR::raiseError("Could not validate the readme.txt file. Have you run it against the validator?"); } else{ // let's inject the screenshots if there are any if (isset($plugin_info['sections']['screenshots']) and count($screenshots = SelfHostedPluginContainer::getScreenshots($PluginZip))){ $m = $plugin_info['sections']['screenshots']; $m = str_replace('
',$m); $m = str_replace('