/** * Lock a single resource key * * @param $path string * @param $type integer * @return Status */ protected function doSingleLock($path, $type) { $status = Status::newGood(); if (isset($this->locksHeld[$path][$type])) { ++$this->locksHeld[$path][$type]; } elseif (isset($this->locksHeld[$path][self::LOCK_EX])) { $this->locksHeld[$path][$type] = 1; } else { wfSuppressWarnings(); $handle = fopen($this->getLockPath($path), 'a+'); wfRestoreWarnings(); if (!$handle) { // lock dir missing? wfMkdirParents($this->lockDir); $handle = fopen($this->getLockPath($path), 'a+'); // try again } if ($handle) { // Either a shared or exclusive lock $lock = $type == self::LOCK_SH ? LOCK_SH : LOCK_EX; if (flock($handle, $lock | LOCK_NB)) { // Record this lock as active $this->locksHeld[$path][$type] = 1; $this->handles[$path][$type] = $handle; } else { fclose($handle); $status->fatal('lockmanager-fail-acquirelock', $path); } } else { $status->fatal('lockmanager-fail-openlock', $path); } } return $status; }
function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0) { global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath; if (!$this->normaliseParams($image, $params)) { return new TransformParameterError($params); } $clientWidth = $params['width']; $clientHeight = $params['height']; $physicalWidth = $params['physicalWidth']; $physicalHeight = $params['physicalHeight']; $srcPath = $image->getPath(); if ($flags & self::TRANSFORM_LATER) { return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } if (!wfMkdirParents(dirname($dstPath))) { return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, wfMsg('thumbnail_dest_directory')); } $status = $this->rasterize($srcPath, $dstPath, $physicalWidth, $physicalHeight); if ($status === true) { return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } else { return $status; // MediaTransformError } }
function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0) { global $wgFLVConverters, $wgFLVConverter, $wgFLVConverterPath; if (!$this->normaliseParams($image, $params)) { return new TransformParameterError($params); } $clientWidth = $params['width']; $clientHeight = $params['height']; $physicalWidth = $params['physicalWidth']; $physicalHeight = $params['physicalHeight']; $srcPath = $image->getPath(); if ($flags & self::TRANSFORM_LATER) { return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } if (!wfMkdirParents(dirname($dstPath), null, __METHOD__)) { return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, wfMsg('thumbnail_dest_directory')); } $err = false; if (isset($wgFLVConverters[$wgFLVConverter])) { $cmd = str_replace(array('$path/', '$width', '$height', '$input', '$output'), array($wgFLVConverterPath ? wfEscapeShellArg("{$wgFLVConverterPath}/") : "", intval($physicalWidth), intval($physicalHeight), wfEscapeShellArg($srcPath), wfEscapeShellArg($dstPath)), $wgFLVConverters[$wgFLVConverter]) . " 2>&1"; wfProfileIn('rsvg'); wfDebug(__METHOD__ . ": {$cmd}\n"); $err = wfShellExec($cmd, $retval); wfProfileOut('rsvg'); } $removed = $this->removeBadFile($dstPath, $retval); if ($retval != 0 || $removed) { wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd)); return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err); } else { return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } }
private static function dataDirOKmaybeCreate($dir, $create = false) { if (!is_dir($dir)) { if (!is_writable(dirname($dir))) { $webserverGroup = Installer::maybeGetWebserverPrimaryGroup(); if ($webserverGroup !== null) { return Status::newFatal('config-sqlite-parent-unwritable-group', $dir, dirname($dir), basename($dir), $webserverGroup); } else { return Status::newFatal('config-sqlite-parent-unwritable-nogroup', $dir, dirname($dir), basename($dir)); } } # Called early on in the installer, later we just want to sanity check # if it's still writable if ($create) { wfSuppressWarnings(); $ok = wfMkdirParents($dir, 0700); wfRestoreWarnings(); if (!$ok) { return Status::newFatal('config-sqlite-mkdir-error', $dir); } # Put a .htaccess file in in case the user didn't take our advice file_put_contents("{$dir}/.htaccess", "Deny from all\n"); } } if (!is_writable($dir)) { return Status::newFatal('config-sqlite-dir-unwritable', $dir); } # We haven't blown up yet, fall through return Status::newGood(); }
function run() { global $wgExtensionMessagesFiles, $wgMessageCache, $IP; $nameHash = md5(implode("\n", array_keys($wgExtensionMessagesFiles))); $dir = "{$IP}/cache/ext-msgs"; wfMkdirParents($dir); $db = dba_open("{$dir}/{$nameHash}.cdb", 'n', 'cdb'); if (!$db) { echo "Cannot open DB file\n"; exit(1); } # Load extension messages foreach ($wgExtensionMessagesFiles as $file) { $messages = $magicWords = array(); require $file; foreach ($messages as $lang => $unused) { $wgMessageCache->processMessagesArray($messages, $lang); } } # Write them to the file foreach ($wgMessageCache->mExtensionMessages as $lang => $messages) { foreach ($messages as $key => $text) { dba_insert("{$lang}:{$key}", $text, $db); } } dba_close($db); }
function execute() { global $wgRequest; if ( !$wgRequest->wasPosted() ) { echo $this->dtd(); echo <<<EOT <html> <head><title>store.php Test Interface</title></head> <body> <form method="post" action="store.php" enctype="multipart/form-data" > <p>File: <input type="file" name="file"/></p> <p><input type="submit" value="OK"/></p> </form></body></html> EOT; return true; } $srcFile = $wgRequest->getFileTempname( 'file' ); if ( !$srcFile ) { $this->error( 400, 'webstore_no_file' ); return false; } // Use an hourly timestamped directory for easy cleanup $now = time(); $this->cleanupTemp( $now ); $timestamp = gmdate( self::$tempDirFormat, $now ); if ( !wfMkdirParents( "{$this->tmpDir}/$timestamp", null, __METHOD__ ) ) { $this->error( 500, 'webstore_dest_mkdir' ); return false; } // Get the extension of the upload, needs to be preserved for type detection $name = $wgRequest->getFileName( 'file' ); $n = strrpos( $name, '.' ); if ( $n ) { $extension = '.' . File::normalizeExtension( substr( $name, $n + 1 ) ); } else { $extension = ''; } // Pick a random temporary path $destRel = $timestamp . '/' . md5( mt_rand() . mt_rand() . mt_rand() ) . $extension; if ( !@move_uploaded_file( $srcFile, "{$this->tmpDir}/$destRel" ) ) { $this->error( 400, 'webstore_move_uploaded', $srcFile, "{$this->tmpDir}/$destRel" ); return false; } // Succeeded, return temporary location header( 'Content-Type: text/xml' ); echo <<<EOT <?xml version="1.0" encoding="utf-8"?> <response> <location>$destRel</location> </response> EOT; return true; }
public function execute() { global $wgCaptchaSecret, $wgCaptchaDirectoryLevels; $instance = ConfirmEditHooks::getInstance(); if (!$instance instanceof FancyCaptcha) { $this->error("\$wgCaptchaClass is not FancyCaptcha.\n", 1); } $backend = $instance->getBackend(); $countAct = $instance->estimateCaptchaCount(); $this->output("Estimated number of captchas is {$countAct}.\n"); $countGen = (int) $this->getOption('fill') - $countAct; if ($countGen <= 0) { $this->output("No need to generate anymore captchas.\n"); return; } $tmpDir = wfTempDir() . '/mw-fancycaptcha-' . time() . '-' . wfRandomString(6); if (!wfMkdirParents($tmpDir)) { $this->error("Could not create temp directory.\n", 1); } $e = null; // exception try { $cmd = sprintf("python %s --key %s --output %s --count %s --dirs %s", wfEscapeShellArg(__DIR__ . '/../captcha.py'), wfEscapeShellArg($wgCaptchaSecret), wfEscapeShellArg($tmpDir), wfEscapeShellArg($countGen), wfEscapeShellArg($wgCaptchaDirectoryLevels)); foreach (array('wordlist', 'font', 'font-size', 'blacklist', 'verbose') as $par) { if ($this->hasOption($par)) { $cmd .= " --{$par} " . wfEscapeShellArg($this->getOption($par)); } } $this->output("Generating {$countGen} new captchas...\n"); $retVal = 1; wfShellExec($cmd, $retVal, array(), array('time' => 0)); if ($retVal != 0) { wfRecursiveRemoveDir($tmpDir); $this->error("Could not run generation script.\n", 1); } $flags = FilesystemIterator::SKIP_DOTS; $iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tmpDir, $flags), RecursiveIteratorIterator::CHILD_FIRST); $this->output("Copying the new captchas to storage...\n"); foreach ($iter as $fileInfo) { if (!$fileInfo->isFile()) { continue; } list($salt, $hash) = $instance->hashFromImageName($fileInfo->getBasename()); $dest = $instance->imagePath($salt, $hash); $backend->prepare(array('dir' => dirname($dest))); $status = $backend->quickStore(array('src' => $fileInfo->getPathname(), 'dst' => $dest)); if (!$status->isOK()) { $this->error("Could not save file '{$fileInfo->getPathname()}'.\n"); } } } catch (Exception $e) { wfRecursiveRemoveDir($tmpDir); throw $e; } $this->output("Removing temporary files...\n"); wfRecursiveRemoveDir($tmpDir); $this->output("Done.\n"); }
/** * Run PHP Storm's Code Inspect for a given directory * * Actually, PHP storm will be run for a given directory. * XML reports will then be parsed to get issues for given file. * * @param string $dirName file to run Code Inspect for * @return string output from Code Inspect * @throws Exception */ protected function inspectDirectory($dirName) { global $wgPHPStormPath, $IP; $start = microtime(true); $dirName = realpath($dirName); $isCached = $this->cache['directory'] !== '' && strpos($dirName, $this->cache['directory']) === 0; if (!$isCached) { $lintProfile = dirname(__FILE__) . '/php/profiles/phplint.xml'; $projectMetaData = dirname(__FILE__) . '/php/project'; // copy project meta data to trunk root $copyCmd = "cp -rf {$projectMetaData}/.idea {$IP}"; echo "Copying project meta data <{$copyCmd}>..."; exec($copyCmd); echo " [done]\n"; // create a temporary directory for Code Inspect results $resultsDir = wfTempDir() . '/phpstorm/' . uniqid('lint'); echo "Creating temporary directory for results <{$resultsDir}>..."; if (wfMkdirParents($resultsDir)) { echo " [done]\n"; } else { echo " [err!]\n"; } $cmd = sprintf('/bin/sh %s/inspect.sh %s %s %s -d %s -v2', $wgPHPStormPath, realpath($IP . '/includes/..'), $lintProfile, $resultsDir, $dirName); echo "Running PHP storm <{$cmd}>..."; #echo "Running PhpStorm for <{$dirName}>..."; $retVal = 0; $output = array(); exec($cmd, $output, $retVal); if ($retVal !== 0) { throw new Exception("{$cmd} ended with code #{$retVal}"); } // get the version of PhpStorm $tool = ''; foreach ($output as $line) { if (strpos($line, 'Starting up JetBrains PhpStorm') !== false) { preg_match('#JetBrains PhpStorm [\\d\\.]+#', $line, $matches); $tool = $matches[0]; } } echo implode("\n", $output); // debug echo " [done]\n"; // format results $output = array('problems' => $this->parseResults($resultsDir), 'tool' => $tool); // update the cache $this->cache = array('directory' => $dirName, 'output' => $output); } else { //echo "Got results from cache for <{$this->cache['directory']}>\n"; $output = $this->cache['output']; } $output['time'] = round(microtime(true) - $start, 4); return $output; }
static function get( $options ){ global $wgFFmpegLocation, $wgOggThumbLocation; // Set up lodal pointer to file $file = $options['file']; if( !is_dir( dirname( $options['dstPath'] ) ) ){ wfMkdirParents( dirname( $options['dstPath'] ), null, __METHOD__ ); } wfDebug( "Creating video thumbnail at" . $options['dstPath'] . "\n" ); // Else try ffmpeg and return result: return self::tryFfmpegThumb( $options ); }
private function generate() { if (preg_match('/^\\s*(\\w+)\\s*{/', $this->source, $matches)) { $diagram_type = $matches[1]; } else { $diagram_type = 'blockdiag'; // blockdiag for default } $diagprog_path = $this->path_array[$diagram_type]; if (!is_file($diagprog_path)) { return $this->error("{$diagram_type} is not found at the specified place."); } // temporary directory check if (!file_exists($this->tmpDir)) { if (!wfMkdirParents($this->tmpDir)) { return $this->error('temporary directory is not found.'); } } elseif (!is_dir($this->tmpDir)) { return $this->error('temporary directory is not directory'); } elseif (!is_writable($this->tmpDir)) { return $this->error('temporary directory is not writable'); } // create temporary file $dstTmpName = tempnam($this->tmpDir, 'blockdiag'); $srcTmpName = tempnam($this->tmpDir, 'blockdiag'); // write blockdiag source $fp = fopen($srcTmpName, 'w'); fwrite($fp, $this->source); fclose($fp); // generate blockdiag image $cmd = $diagprog_path . ' -T ' . escapeshellarg($this->imgType) . ' -o ' . escapeshellarg($dstTmpName) . ' ' . escapeshellarg($srcTmpName); $res = `{$cmd}`; if (filesize($dstTmpName) == 0) { return $this->error('unknown error.'); } // move to image directory $hashpath = $this->getHashPath(); if (!file_exists($hashpath)) { if (!@wfMkdirParents($hashpath, 0755)) { return $this->error('can not make blockdiag image directory', $this->blockdiagDir); } } elseif (!is_dir($hashpath)) { return $this->error('blockdiag image directory is already exists. but not directory'); } elseif (!is_writable($hashpath)) { return $this->error('blockdiag image directory is not writable'); } if (!rename("{$dstTmpName}", "{$hashpath}/{$this->hash}.png")) { return $this->error('can not rename blockdiag image'); } return $this->mkImageTag(); }
/** * Constructor */ function __construct($server = false, $user = false, $password = false, $dbName = false, $failFunction = false, $flags = 0) { global $wgOut, $wgSQLiteDataDir, $wgSQLiteDataDirMode; if ("{$wgSQLiteDataDir}" == '') { $wgSQLiteDataDir = dirname($_SERVER['DOCUMENT_ROOT']) . '/data'; } if (!is_dir($wgSQLiteDataDir)) { wfMkdirParents($wgSQLiteDataDir, $wgSQLiteDataDirMode); } $this->mFailFunction = $failFunction; $this->mFlags = $flags; $this->mDatabaseFile = "{$wgSQLiteDataDir}/{$dbName}.sqlite"; $this->open($server, $user, $password, $dbName); }
public function startWrite($code) { if (!file_exists($this->directory)) { if (!wfMkdirParents($this->directory, null, __METHOD__)) { throw new MWException("Unable to create the localisation store " . "directory \"{$this->directory}\""); } } // Close reader to stop permission errors on write if (!empty($this->readers[$code])) { $this->readers[$code]->close(); } try { $this->writer = Writer::open($this->getFileName($code)); } catch (Exception $e) { throw new MWException($e->getMessage()); } $this->currentLang = $code; }
function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0) { global $wgDjvuRenderer, $wgDjvuPostProcessor; // Fetch XML and check it, to give a more informative error message than the one which // normaliseParams will inevitably give. $xml = $image->getMetadata(); if (!$xml) { return new MediaTransformError('thumbnail_error', @$params['width'], @$params['height'], wfMsg('djvu_no_xml')); } if (!$this->normaliseParams($image, $params)) { return new TransformParameterError($params); } $width = $params['width']; $height = $params['height']; $srcPath = $image->getPath(); $page = $params['page']; if ($page > $this->pageCount($image)) { return new MediaTransformError('thumbnail_error', $width, $height, wfMsg('djvu_page_error')); } if ($flags & self::TRANSFORM_LATER) { return new ThumbnailImage($image, $dstUrl, $width, $height, $dstPath, $page); } if (!wfMkdirParents(dirname($dstPath))) { return new MediaTransformError('thumbnail_error', $width, $height, wfMsg('thumbnail_dest_directory')); } # Use a subshell (brackets) to aggregate stderr from both pipeline commands # before redirecting it to the overall stdout. This works in both Linux and Windows XP. $cmd = '(' . wfEscapeShellArg($wgDjvuRenderer) . " -format=ppm -page={$page} -size={$width}x{$height} " . wfEscapeShellArg($srcPath); if ($wgDjvuPostProcessor) { $cmd .= " | {$wgDjvuPostProcessor}"; } $cmd .= ' > ' . wfEscapeShellArg($dstPath) . ') 2>&1'; wfProfileIn('ddjvu'); wfDebug(__METHOD__ . ": {$cmd}\n"); $err = wfShellExec($cmd, $retval); wfProfileOut('ddjvu'); $removed = $this->removeBadFile($dstPath, $retval); if ($retval != 0 || $removed) { wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd)); return new MediaTransformError('thumbnail_error', $width, $height, $err); } else { return new ThumbnailImage($image, $dstUrl, $width, $height, $dstPath, $page); } }
function doJobLoop(){ global $wgJobTypeConfig, $wahJobDelay, $wahRunOnce, $wahStatusOutput; //look for jobs (sleep for $wahJobDelay if none found) $job = WahJobManager :: getNewJob(false, 'Internal'); if(!$job && $wahRunOnce == false){ if($wahStatusOutput) print "no jobs found waiting $wahJobDelay \n"; sleep($wahJobDelay); return doJobLoop(); }elseif(!$job && $wahRunOnce == true){ if($wahStatusOutput) print "no job found \n"; return ; } $jobSet = WahJobManager ::getJobSetById( $job->job_set_id ); $jobDetails = FormatJson::decode( $job->job_json ) ; //get the title (so we can access the source file) $fTitle = Title::newFromText( $job->title, $job->ns ); $file = wfLocalFile( $fTitle ); $thumbPath = $file->getThumbPath( $jobSet->set_encodekey ); //make sure the directory is ready: wfMkdirParents( $thumbPath, null, __METHOD__ ); $destTarget = $thumbPath . '.ogg'; //issue the encoding command if($wahStatusOutput) print "Running Encode Command...\n"; wahDoEncode($file->getPath(), $destTarget, $jobDetails->encodeSettings ); //once done with encode update the status: WahJobManager :: updateJobDone($job); //update set done (if only one item in the set) $wjm = WahJobManager::newFromSet( $jobSet ); $percDone = $wjm->getDonePerc(); if( $percDone == 1 ){ WahJobManager :: updateSetDone( $jobSet ); }else{ if($wahStatusOutput) print "job not complete? (might be mixing chunkDuration types?) "; } }
/** * checkImageDirectory * * check if target directory exists. if not create it. if not possible * signalize it. We have to have id of target wiki * * @access public * @author eloy@wikia * * @return boolean: status of operation */ public function checkImageDirectory() { $mRetVal = false; if (empty($this->mTargetID)) { return $mRetVal; } wfProfileIn(__METHOD__); $UploadDirectory = WikiFactory::getVarValueByName("wgUploadDirectory", $this->mTargetID); if (file_exists($UploadDirectory)) { if (is_dir($UploadDirectory)) { $this->addLog("Target {$UploadDirectory} exists and is directory."); $mRetVal = true; } else { $this->addLog("Target {$UploadDirectory} exists but is not directory"); $mRetVal = false; } } else { $mRetVal = wfMkdirParents($UploadDirectory); } wfProfileOut(__METHOD__); return $mRetVal; }
/** * main entry point, create wiki with given parameters * * @throw CreateWikiException an exception with status of operation set */ public function create() { global $wgExternalSharedDB, $wgSharedDB, $wgUser; $then = microtime(true); // Set this flag to ensure that all select operations go against master // Slave lag can cause random errors during wiki creation process global $wgForceMasterDatabase; $wgForceMasterDatabase = true; wfProfileIn(__METHOD__); if (wfReadOnly()) { wfProfileOut(__METHOD__); throw new CreateWikiException('DB is read only', self::ERROR_READONLY); } // check founder if ($this->mFounder->isAnon()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Founder is anon', self::ERROR_USER_IN_ANON); } // check executables $status = $this->checkExecutables(); if ($status != 0) { wfProfileOut(__METHOD__); throw new CreateWikiException('checkExecutables() failed', $status); } // check domains $status = $this->checkDomain(); if ($status != 0) { wfProfileOut(__METHOD__); throw new CreateWikiException('Check domain failed', $status); } // prepare all values needed for creating wiki $this->prepareValues(); // prevent domain to be registered more than once if (!AutoCreateWiki::lockDomain($this->mDomain)) { wfProfileOut(__METHOD__); throw new CreateWikiException('Domain name taken', self::ERROR_DOMAIN_NAME_TAKEN); } // start counting time $this->mCurrTime = wfTime(); // check and create database $this->mDBw = wfGetDB(DB_MASTER, array(), $wgExternalSharedDB); # central /// // local database handled is handler to cluster we create new wiki. // It doesn't have to be the same like wikifactory cluster or db cluster // where Special:CreateWiki exists. // // @todo do not use hardcoded name, code below is only for test // // set $activeCluster to false if you want to create wikis on first // cluster // $this->mClusterDB = self::ACTIVE_CLUSTER ? "wikicities_" . self::ACTIVE_CLUSTER : "wikicities"; $this->mNewWiki->dbw = wfGetDB(DB_MASTER, array(), $this->mClusterDB); // database handler, old $dbwTarget // check if database is creatable // @todo move all database creation checkers to canCreateDatabase if (!$this->canCreateDatabase()) { wfProfileOut(__METHOD__); throw new CreateWikiException('DB exists - ' . $this->mNewWiki->dbname, self::ERROR_DATABASE_ALREADY_EXISTS); } else { $this->mNewWiki->dbw->query(sprintf("CREATE DATABASE `%s`", $this->mNewWiki->dbname)); wfDebugLog("createwiki", "Database {$this->mNewWiki->dbname} created\n", true); } /** * create position in wiki.factory * (I like sprintf construction, so sue me) */ if (!$this->addToCityList()) { wfDebugLog("createwiki", __METHOD__ . ": Cannot set data in city_list table\n", true); wfProfileOut(__METHOD__); throw new CreateWikiException('Cannot add wiki to city_list', self::ERROR_DATABASE_WRITE_TO_CITY_LIST_BROKEN); } // set new city_id $this->mNewWiki->city_id = $this->mDBw->insertId(); if (empty($this->mNewWiki->city_id)) { wfProfileOut(__METHOD__); throw new CreateWikiException('Cannot set data in city_list table. city_id is empty after insert', self::ERROR_DATABASE_WIKI_FACTORY_TABLES_BROKEN); } wfDebugLog("createwiki", __METHOD__ . ": Row added added into city_list table, city_id = {$this->mNewWiki->city_id}\n", true); /** * add domain and www.domain to the city_domains table */ if (!$this->addToCityDomains()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Cannot set data in city_domains table', self::ERROR_DATABASE_WRITE_TO_CITY_DOMAINS_BROKEN); } wfDebugLog("createwiki", __METHOD__ . ": Row added into city_domains table, city_id = {$this->mNewWiki->city_id}\n", true); /** * create image folder */ global $wgEnableSwiftFileBackend; if (empty($wgEnableSwiftFileBackend)) { wfMkdirParents("{$this->mNewWiki->images_dir}"); wfDebugLog("createwiki", __METHOD__ . ": Folder {$this->mNewWiki->images_dir} created\n", true); } // Force initialize uploader user from correct shared db $uploader = User::newFromName('CreateWiki script'); $uploader->getId(); $oldUser = $wgUser; $wgUser = $uploader; /** * wikifactory variables */ wfDebugLog("createwiki", __METHOD__ . ": Populating city_variables\n", true); $this->setWFVariables(); $tmpSharedDB = $wgSharedDB; $wgSharedDB = $this->mNewWiki->dbname; $this->mDBw->commit(__METHOD__); // commit shared DB changes /** * we got empty database created, now we have to create tables and * populate it with some default values */ wfDebugLog("createwiki", __METHOD__ . ": Creating tables in database\n", true); $this->mNewWiki->dbw = wfGetDB(DB_MASTER, array(), $this->mNewWiki->dbname); if (!$this->createTables()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Creating tables not finished', self::ERROR_SQL_FILE_BROKEN); } /** * import language starter */ if (!$this->importStarter()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Starter import failed', self::ERROR_SQL_FILE_BROKEN); } /** * making the wiki founder a sysop/bureaucrat */ wfDebugLog("createwiki", __METHOD__ . ": Create user sysop/bureaucrat for user: {$this->mNewWiki->founderId} \n", true); if (!$this->addUserToGroups()) { wfDebugLog("createwiki", __METHOD__ . ": Create user sysop/bureaucrat for user: {$this->mNewWiki->founderId} failed \n", true); } /** * init site_stats table (add empty row) */ $this->mNewWiki->dbw->insert("site_stats", array("ss_row_id" => "1"), __METHOD__); /** * copy default logo */ $res = ImagesService::uploadImageFromUrl(self::CREATEWIKI_LOGO, (object) ['name' => 'Wiki.png'], $uploader); if ($res['status'] === true) { wfDebugLog("createwiki", __METHOD__ . ": Default logo has been uploaded\n", true); } else { wfDebugLog("createwiki", __METHOD__ . ": Default logo has not been uploaded - " . print_r($res['errors'], true) . "\n", true); } /** * destroy connection to newly created database */ $this->waitForSlaves(__METHOD__); $wgSharedDB = $tmpSharedDB; $oHub = WikiFactoryHub::getInstance(); $oHub->setVertical($this->mNewWiki->city_id, $this->mNewWiki->vertical, "CW Setup"); wfDebugLog("createwiki", __METHOD__ . ": Wiki added to the vertical: {$this->mNewWiki->vertical} \n", true); for ($i = 0; $i < count($this->mNewWiki->categories); $i++) { $oHub->addCategory($this->mNewWiki->city_id, $this->mNewWiki->categories[$i]); wfDebugLog("createwiki", __METHOD__ . ": Wiki added to the category: {$this->mNewWiki->categories[$i]} \n", true); } /** * define wiki type */ $wiki_type = 'default'; /** * modify variables */ global $wgUniversalCreationVariables; if (!empty($wgUniversalCreationVariables) && !empty($wiki_type) && isset($wgUniversalCreationVariables[$wiki_type])) { $this->addCustomSettings(0, $wgUniversalCreationVariables[$wiki_type], "universal"); wfDebugLog("createwiki", __METHOD__ . ": Custom settings added for wiki_type: {$wiki_type} \n", true); } /** * set variables per language */ global $wgLangCreationVariables; $langCreationVar = isset($wgLangCreationVariables[$wiki_type]) ? $wgLangCreationVariables[$wiki_type] : $wgLangCreationVariables; $this->addCustomSettings($this->mNewWiki->language, $langCreationVar, "language"); wfDebugLog("createwiki", __METHOD__ . ": Custom settings added for wiki_type: {$wiki_type} and language: {$this->mNewWiki->language} \n", true); /** * set tags per language and per hub * @FIXME the switch is !@#$ creazy, but I didn't find a core function */ $tags = new WikiFactoryTags($this->mNewWiki->city_id); $langTag = $this->mNewWiki->language; if ($langTag !== 'en') { switch ($langTag) { case 'pt-br': $langTag = 'pt'; break; case 'zh-tw': case 'zh-hk': case 'zh-clas': case 'zh-class': case 'zh-classical': case 'zh-cn': case 'zh-hans': case 'zh-hant': case 'zh-min-': case 'zh-min-n': case 'zh-mo': case 'zh-sg': case 'zh-yue': $langTag = 'zh'; break; } $tags->addTagsByName($langTag); } /** * move main page -> this code exists in CreateWikiLocalJob - so it is not needed anymore */ /** * Unset database from mNewWiki, because database objects cannot be serialized from MW1.19 */ unset($this->mNewWiki->dbw); // Restore wgUser $wgUser = $oldUser; unset($oldUser); /** * Schedule an async task */ $creationTask = new \Wikia\Tasks\Tasks\CreateNewWikiTask(); $job_params = new stdClass(); foreach ($this->mNewWiki as $id => $value) { if (!is_object($value)) { $job_params->{$id} = $value; } } // BugId:15644 - I need to pass this to CreateWikiLocalJob::changeStarterContributions $job_params->sDbStarter = $this->sDbStarter; $task_id = (new \Wikia\Tasks\AsyncTaskList())->wikiId($this->mNewWiki->city_id)->prioritize()->add($creationTask->call('postCreationSetup', $job_params))->add($creationTask->call('maintenance', rtrim($this->mNewWiki->url, "/")))->queue(); wfDebugLog("createwiki", __METHOD__ . ": Local maintenance task added as {$task_id}\n", true); $this->info(__METHOD__ . ': done', ['task_id' => $task_id, 'took' => microtime(true) - $then]); wfProfileOut(__METHOD__); }
protected function checkCacheDirs() { $filename = $this->fileCacheName(); $mydir2 = substr($filename, 0, strrpos($filename, '/')); # subdirectory level 2 $mydir1 = substr($mydir2, 0, strrpos($mydir2, '/')); # subdirectory level 1 wfMkdirParents($mydir1); wfMkdirParents($mydir2); }
/** * dump directory is created as * * <root>/<first letter>/<two first letters>/<database> */ function getDirectory($database, $hide = false) { global $wgDevelEnvironment; $folder = empty($wgDevelEnvironment) ? "raid" : "tmp"; $subfolder = $hide ? "dumps-hidden" : "dumps"; $database = strtolower($database); $directory = sprintf("/%s/%s/%s/%s/%s", $folder, $subfolder, substr($database, 0, 1), substr($database, 0, 2), $database); if (!is_dir($directory)) { Wikia::log(__METHOD__, "dir", "create {$directory}", true, true); wfMkdirParents($directory); } return $directory; }
/** I BORROWED THIS FUNCTION FROM SpecialUpload.php!! CHECK FOR EACH VERSION OF MEDIAWIKI, IF * THIS FUNCTION STILL MAKES SENSE! * * Move the uploaded file from its temporary location to the final * destination. If a previous version of the file exists, move * it into the archive subdirectory. * * @todo If the later save fails, we may have disappeared the original file. * * @param string $saveName * @param string $tempName full path to the temporary file * @param bool $useRename if true, doesn't check that the source file * is a PHP-managed upload temporary */ function saveUploadedFile($saveName, $tempName, $useRename = false) { global $wgOut, $wgAllowCopyUploads; $fname = "SpecialUpload::saveUploadedFile"; if (!$useRename && $wgAllowCopyUploads && $this->mSourceType == 'web') { $useRename = true; } $dest = wfImageDir($saveName); $archive = wfImageArchiveDir($saveName); if (!is_dir($dest)) { wfMkdirParents($dest); } if (!is_dir($archive)) { wfMkdirParents($archive); } $this->mSavedFile = "{$dest}/{$saveName}"; if (is_file($this->mSavedFile)) { $this->mUploadOldVersion = gmdate('YmdHis') . "!{$saveName}"; wfSuppressWarnings(); $success = rename($this->mSavedFile, "{$archive}/{$this->mUploadOldVersion}"); wfRestoreWarnings(); if (!$success) { $wgOut->showFileRenameError($this->mSavedFile, "{$archive}/{$this->mUploadOldVersion}"); return false; } else { wfDebug("{$fname}: moved file " . $this->mSavedFile . " to {$archive}/{$this->mUploadOldVersion}\n"); } } else { $this->mUploadOldVersion = ''; } wfSuppressWarnings(); $success = $useRename ? rename($tempName, $this->mSavedFile) : move_uploaded_file($tempName, $this->mSavedFile); wfRestoreWarnings(); if (!$success) { $wgOut->showFileCopyError($tempName, $this->mSavedFile); return false; } else { wfDebug("{$fname}: wrote tempfile {$tempName} to " . $this->mSavedFile . "\n"); } chmod($this->mSavedFile, 0644); return true; }
/** * Sets up requires directories * @param DatabaseUpdater $updater Provided by MediaWikis update.php * @return boolean Always true to keep the hook running */ public static function getSchemaUpdates($updater) { //TODO: Create abstraction in Core/Adapter $sTmpDir = BSDATADIR . DS . 'UEModulePDF'; if (!file_exists($sTmpDir)) { echo 'Directory "' . $sTmpDir . '" not found. Creating.' . "\n"; wfMkdirParents($sTmpDir); } else { echo 'Directory "' . $sTmpDir . '" found.' . "\n"; } $sDefaultTemplateDir = BSDATADIR . DS . 'PDFTemplates'; if (!file_exists($sDefaultTemplateDir)) { echo 'Default template directory "' . $sDefaultTemplateDir . '" not found. Copying.' . "\n"; BsFileSystemHelper::copyRecursive(__DIR__ . DS . 'data' . DS . 'PDFTemplates', $sDefaultTemplateDir); } return true; }
function revert() { global $wgOut, $wgRequest, $wgUser; $oldimage = $wgRequest->getText('oldimage'); if (strlen($oldimage) < 16) { $wgOut->showUnexpectedValueError('oldimage', htmlspecialchars($oldimage)); return; } if (strstr($oldimage, "/") || strstr($oldimage, "\\")) { $wgOut->showUnexpectedValueError('oldimage', htmlspecialchars($oldimage)); return; } if (wfReadOnly()) { $wgOut->readOnlyPage(); return; } if ($wgUser->isAnon()) { $wgOut->showErrorPage('uploadnologin', 'uploadnologintext'); return; } if (!$this->mTitle->userCanEdit()) { $wgOut->sysopRequired(); return; } if ($wgUser->isBlocked()) { return $this->blockedIPpage(); } if (!$wgUser->matchEditToken($wgRequest->getVal('wpEditToken'), $oldimage)) { $wgOut->showErrorPage('internalerror', 'sessionfailure'); return; } $name = substr($oldimage, 15); $dest = wfImageDir($name); $archive = wfImageArchiveDir($name); $curfile = "{$dest}/{$name}"; if (!is_dir($dest)) { wfMkdirParents($dest); } if (!is_dir($archive)) { wfMkdirParents($archive); } if (!is_file($curfile)) { $wgOut->showFileNotFoundError(htmlspecialchars($curfile)); return; } $oldver = wfTimestampNow() . "!{$name}"; $dbr =& wfGetDB(DB_SLAVE); $size = $dbr->selectField('oldimage', 'oi_size', array('oi_archive_name' => $oldimage)); if (!rename($curfile, "{$archive}/{$oldver}")) { $wgOut->showFileRenameError($curfile, "{$archive}/{$oldver}"); return; } if (!copy("{$archive}/{$oldimage}", $curfile)) { $wgOut->showFileCopyError("{$archive}/{$oldimage}", $curfile); return; } # Record upload and update metadata cache $img = Image::newFromName($name); $img->recordUpload($oldver, wfMsg("reverted")); $wgOut->setPagetitle(wfMsg('actioncomplete')); $wgOut->setRobotpolicy('noindex,nofollow'); $wgOut->addHTML(wfMsg('imagereverted')); $descTitle = $img->getTitle(); $wgOut->returnToMain(false, $descTitle->getPrefixedText()); }
/** * @covers ::wfMkdirParents */ public function testWfMkdirParents() { // Should not return true if file exists instead of directory $fname = $this->getNewTempFile(); MediaWiki\suppressWarnings(); $ok = wfMkdirParents($fname); MediaWiki\restoreWarnings(); $this->assertFalse($ok); }
/** * Moves an image from a safe private location * Caller is responsible for clearing caches * @param File $oimage * @returns mixed, string timestamp on success, false on failure */ function makeOldImagePublic($oimage) { $transaction = new FSTransaction(); if (!FileStore::lock()) { wfDebug(__METHOD__ . " could not acquire filestore lock\n"); return false; } $store = FileStore::get('deleted'); if (!$store) { wfDebug(__METHOD__ . ": skipping row with no file.\n"); return false; } $key = $oimage->sha1 . '.' . $oimage->getExtension(); $destDir = $oimage->getArchivePath(); if (!is_dir($destDir)) { wfMkdirParents($destDir); } $destPath = $destDir . DIRECTORY_SEPARATOR . $oimage->archive_name; // Check if any other stored revisions use this file; // if so, we shouldn't remove the file from the hidden // archives so they will still work. Check hidden files first. $useCount = $this->dbw->selectField('oldimage', '1', array('oi_sha1' => $oimage->sha1, 'oi_deleted & ' . File::DELETED_FILE => File::DELETED_FILE), __METHOD__, array('FOR UPDATE')); // Check the rest of the deleted archives too. // (these are the ones that don't show in the image history) if (!$useCount) { $useCount = $this->dbw->selectField('filearchive', '1', array('fa_storage_group' => 'deleted', 'fa_storage_key' => $key), __METHOD__, array('FOR UPDATE')); } if ($useCount == 0) { wfDebug(__METHOD__ . ": nothing else using {$oimage->sha1}, will deleting after\n"); $flags = FileStore::DELETE_ORIGINAL; } else { $flags = 0; } $transaction->add($store->export($key, $destPath, $flags)); wfDebug(__METHOD__ . ": set db items, applying file transactions\n"); $transaction->commit(); FileStore::unlock(); $m = explode('!', $oimage->archive_name, 2); $timestamp = $m[0]; return $timestamp; }
/** * obtains a new temporary directory * * The obtained directory is enlisted to be removed (recursively with all its contained * files) upon tearDown. * * @since 1.20 * * @return string Absolute name of the temporary directory */ protected function getNewTempDirectory() { // Starting of with a temporary /file/. $fileName = $this->getNewTempFile(); // Converting the temporary /file/ to a /directory/ // The following is not atomic, but at least we now have a single place, // where temporary directory creation is bundled and can be improved unlink($fileName); $this->assertTrue(wfMkdirParents($fileName)); return $fileName; }
/** * Stash a file in a temporary directory for later processing * after the user has confirmed it. * * If the user doesn't explicitly cancel or accept, these files * can accumulate in the temp directory. * * @param string $saveName - the destination filename * @param string $tempName - the source temporary file to save * @return string - full path the stashed file, or false on failure * @access private */ function saveTempUploadedFile($saveName, $tempName) { global $wgOut; $archive = wfImageArchiveDir($saveName, 'temp'); if (!is_dir($archive)) { wfMkdirParents($archive); } $stash = $archive . '/' . gmdate("YmdHis") . '!' . $saveName; $success = $this->mRemoveTempFile ? rename($tempName, $stash) : move_uploaded_file($tempName, $stash); if (!$success) { $wgOut->showFileCopyError($tempName, $stash); return false; } return $stash; }
$dbc->setMode(DatabaseIbm_db2::INSTALL_MODE); $wgDatabase->setMode(DatabaseIbm_db2::INSTALL_MODE); if (!$wgDatabase->isOpen()) { print " error: " . htmlspecialchars($wgDatabase->lastError()) . "</li>\n"; } else { $myver = $wgDatabase->getServerVersion(); } if (is_callable(array($wgDatabase, 'initial_setup'))) { $wgDatabase->initial_setup('', $wgDBname); } } elseif ($conf->DBtype == 'sqlite') { $wgSQLiteDataDir = $conf->SQLiteDataDir; echo '<li>Attempting to connect to SQLite database at "' . htmlspecialchars($wgSQLiteDataDir) . '": '; if (!is_dir($wgSQLiteDataDir)) { if (is_writable(dirname($wgSQLiteDataDir))) { $ok = wfMkdirParents($wgSQLiteDataDir, $wgSQLiteDataDirMode); } else { $ok = false; } if (!$ok) { echo "cannot create data directory</li>"; $errs['SQLiteDataDir'] = 'Enter a valid data directory'; continue; } } if (!is_writable($wgSQLiteDataDir)) { echo "data directory not writable</li>"; $errs['SQLiteDataDir'] = 'Enter a writable data directory'; continue; } $dataFile = DatabaseSqlite::generateFileName($wgSQLiteDataDir, $wgDBname);
/** * Returns which scaler type should be used. Creates parent directories * for $dstPath and returns 'client' on error * * @return string client,im,custom,gd */ protected static function getScalerType($dstPath, $checkDstPath = true) { global $wgUseImageResize, $wgUseImageMagick, $wgCustomConvertCommand; if (!$dstPath && $checkDstPath) { # No output path available, client side scaling only $scaler = 'client'; } elseif (!$wgUseImageResize) { $scaler = 'client'; } elseif ($wgUseImageMagick) { $scaler = 'im'; } elseif ($wgCustomConvertCommand) { $scaler = 'custom'; } elseif (function_exists('imagecreatetruecolor')) { $scaler = 'gd'; } elseif (class_exists('Imagick')) { $scaler = 'imext'; } else { $scaler = 'client'; } if ($scaler != 'client' && $dstPath) { if (!wfMkdirParents(dirname($dstPath))) { # Unable to create a path for the thumbnail return 'client'; } } return $scaler; }
function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0) { global $wgUseImageMagick, $wgImageMagickConvertCommand, $wgImageMagickTempDir; global $wgCustomConvertCommand; global $wgSharpenParameter, $wgSharpenReductionThreshold; global $wgMaxAnimatedGifArea; if (!$this->normaliseParams($image, $params)) { return new TransformParameterError($params); } $physicalWidth = $params['physicalWidth']; $physicalHeight = $params['physicalHeight']; $clientWidth = $params['width']; $clientHeight = $params['height']; $srcWidth = $image->getWidth(); $srcHeight = $image->getHeight(); $mimeType = $image->getMimeType(); $srcPath = $image->getPath(); $retval = 0; wfDebug(__METHOD__ . ": creating {$physicalWidth}x{$physicalHeight} thumbnail at {$dstPath}\n"); if (!$image->mustRender() && $physicalWidth == $srcWidth && $physicalHeight == $srcHeight) { # normaliseParams (or the user) wants us to return the unscaled image wfDebug(__METHOD__ . ": returning unscaled image\n"); return new ThumbnailImage($image, $image->getURL(), $clientWidth, $clientHeight, $srcPath); } if (!$dstPath) { // No output path available, client side scaling only $scaler = 'client'; } elseif ($wgUseImageMagick) { $scaler = 'im'; } elseif ($wgCustomConvertCommand) { $scaler = 'custom'; } elseif (function_exists('imagecreatetruecolor')) { $scaler = 'gd'; } else { $scaler = 'client'; } wfDebug(__METHOD__ . ": scaler {$scaler}\n"); if ($scaler == 'client') { # Client-side image scaling, use the source URL # Using the destination URL in a TRANSFORM_LATER request would be incorrect return new ThumbnailImage($image, $image->getURL(), $clientWidth, $clientHeight, $srcPath); } if ($flags & self::TRANSFORM_LATER) { wfDebug(__METHOD__ . ": Transforming later per flags.\n"); return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } if (!wfMkdirParents(dirname($dstPath))) { wfDebug(__METHOD__ . ": Unable to create thumbnail destination directory, falling back to client scaling\n"); return new ThumbnailImage($image, $image->getURL(), $clientWidth, $clientHeight, $srcPath); } if ($scaler == 'im') { # use ImageMagick $quality = ''; $sharpen = ''; $frame = ''; $animation = ''; if ($mimeType == 'image/jpeg') { $quality = "-quality 80"; // 80% # Sharpening, see bug 6193 if (($physicalWidth + $physicalHeight) / ($srcWidth + $srcHeight) < $wgSharpenReductionThreshold) { $sharpen = "-sharpen " . wfEscapeShellArg($wgSharpenParameter); } } elseif ($mimeType == 'image/png') { $quality = "-quality 95"; // zlib 9, adaptive filtering } elseif ($mimeType == 'image/gif') { if ($srcWidth * $srcHeight > $wgMaxAnimatedGifArea) { // Extract initial frame only; we're so big it'll // be a total drag. :P $frame = '[0]'; } else { // Coalesce is needed to scale animated GIFs properly (bug 1017). $animation = ' -coalesce '; } } if (strval($wgImageMagickTempDir) !== '') { $tempEnv = 'MAGICK_TMPDIR=' . wfEscapeShellArg($wgImageMagickTempDir) . ' '; } else { $tempEnv = ''; } # Specify white background color, will be used for transparent images # in Internet Explorer/Windows instead of default black. # Note, we specify "-size {$physicalWidth}" and NOT "-size {$physicalWidth}x{$physicalHeight}". # It seems that ImageMagick has a bug wherein it produces thumbnails of # the wrong size in the second case. $cmd = $tempEnv . wfEscapeShellArg($wgImageMagickConvertCommand) . " {$quality} -background white -size {$physicalWidth} " . wfEscapeShellArg($srcPath . $frame) . $animation . " -thumbnail " . wfEscapeShellArg("{$physicalWidth}x{$physicalHeight}!") . " -depth 8 {$sharpen} " . wfEscapeShellArg($dstPath) . " 2>&1"; wfDebug(__METHOD__ . ": running ImageMagick: {$cmd}\n"); wfProfileIn('convert'); $err = wfShellExec($cmd, $retval); wfProfileOut('convert'); } elseif ($scaler == 'custom') { # Use a custom convert command # Variables: %s %d %w %h $src = wfEscapeShellArg($srcPath); $dst = wfEscapeShellArg($dstPath); $cmd = $wgCustomConvertCommand; $cmd = str_replace('%s', $src, str_replace('%d', $dst, $cmd)); # Filenames $cmd = str_replace('%h', $physicalHeight, str_replace('%w', $physicalWidth, $cmd)); # Size wfDebug(__METHOD__ . ": Running custom convert command {$cmd}\n"); wfProfileIn('convert'); $err = wfShellExec($cmd, $retval); wfProfileOut('convert'); } else { # Use PHP's builtin GD library functions. # # First find out what kind of file this is, and select the correct # input routine for this. $typemap = array('image/gif' => array('imagecreatefromgif', 'palette', 'imagegif'), 'image/jpeg' => array('imagecreatefromjpeg', 'truecolor', array(__CLASS__, 'imageJpegWrapper')), 'image/png' => array('imagecreatefrompng', 'bits', 'imagepng'), 'image/vnd.wap.wbmp' => array('imagecreatefromwbmp', 'palette', 'imagewbmp'), 'image/xbm' => array('imagecreatefromxbm', 'palette', 'imagexbm')); if (!isset($typemap[$mimeType])) { $err = 'Image type not supported'; wfDebug("{$err}\n"); return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err); } list($loader, $colorStyle, $saveType) = $typemap[$mimeType]; if (!function_exists($loader)) { $err = "Incomplete GD library configuration: missing function {$loader}"; wfDebug("{$err}\n"); return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err); } $src_image = call_user_func($loader, $srcPath); $dst_image = imagecreatetruecolor($physicalWidth, $physicalHeight); // Initialise the destination image to transparent instead of // the default solid black, to support PNG and GIF transparency nicely $background = imagecolorallocate($dst_image, 0, 0, 0); imagecolortransparent($dst_image, $background); imagealphablending($dst_image, false); if ($colorStyle == 'palette') { // Don't resample for paletted GIF images. // It may just uglify them, and completely breaks transparency. imagecopyresized($dst_image, $src_image, 0, 0, 0, 0, $physicalWidth, $physicalHeight, imagesx($src_image), imagesy($src_image)); } else { imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $physicalWidth, $physicalHeight, imagesx($src_image), imagesy($src_image)); } imagesavealpha($dst_image, true); call_user_func($saveType, $dst_image, $dstPath); imagedestroy($dst_image); imagedestroy($src_image); $retval = 0; } $removed = $this->removeBadFile($dstPath, $retval); if ($retval != 0 || $removed) { wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd)); return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err); } else { return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } }
/** * Return the imageurl from cache if possible * * If the url has been requested today, get it from cache * Otherwise retrieve remote thumb url, check for local file. * * @param $name String is a dbkey form of a title * @param $width * @param $height * @param String $param Other rendering parameters (page number, etc) from handler's makeParamString. */ function getThumbUrlFromCache($name, $width, $height, $params = "") { global $wgMemc; if (!$this->canCacheThumbs()) { $result = null; // can't pass "null" by reference, but it's ok as default value return $this->getThumbUrl($name, $width, $height, $result, $params); } $key = $this->getLocalCacheKey('ForeignAPIRepo', 'ThumbUrl', $name); $sizekey = "{$width}:{$height}:{$params}"; /* Get the array of urls that we already know */ $knownThumbUrls = $wgMemc->get($key); if (!$knownThumbUrls) { /* No knownThumbUrls for this file */ $knownThumbUrls = array(); } else { if (isset($knownThumbUrls[$sizekey])) { wfDebug(__METHOD__ . ': Got thumburl from local cache: ' . "{$knownThumbUrls[$sizekey]} \n"); return $knownThumbUrls[$sizekey]; } /* This size is not yet known */ } $metadata = null; $foreignUrl = $this->getThumbUrl($name, $width, $height, $metadata, $params); if (!$foreignUrl) { wfDebug(__METHOD__ . " Could not find thumburl\n"); return false; } // We need the same filename as the remote one :) $fileName = rawurldecode(pathinfo($foreignUrl, PATHINFO_BASENAME)); if (!$this->validateFilename($fileName)) { wfDebug(__METHOD__ . " The deduced filename {$fileName} is not safe\n"); return false; } $localPath = $this->getZonePath('thumb') . "/" . $this->getHashPath($name) . $name; $localFilename = $localPath . "/" . $fileName; $localUrl = $this->getZoneUrl('thumb') . "/" . $this->getHashPath($name) . rawurlencode($name) . "/" . rawurlencode($fileName); if (file_exists($localFilename) && isset($metadata['timestamp'])) { wfDebug(__METHOD__ . " Thumbnail was already downloaded before\n"); $modified = filemtime($localFilename); $remoteModified = strtotime($metadata['timestamp']); $current = time(); $diff = abs($modified - $current); if ($remoteModified < $modified && $diff < $this->fileCacheExpiry) { /* Use our current and already downloaded thumbnail */ $knownThumbUrls[$sizekey] = $localUrl; $wgMemc->set($key, $knownThumbUrls, $this->apiThumbCacheExpiry); return $localUrl; } /* There is a new Commons file, or existing thumbnail older than a month */ } $thumb = self::httpGet($foreignUrl); if (!$thumb) { wfDebug(__METHOD__ . " Could not download thumb\n"); return false; } if (!is_dir($localPath)) { if (!wfMkdirParents($localPath)) { wfDebug(__METHOD__ . " could not create directory {$localPath} for thumb\n"); return $foreignUrl; } } # @todo FIXME: Delete old thumbs that aren't being used. Maintenance script? wfSuppressWarnings(); if (!file_put_contents($localFilename, $thumb)) { wfRestoreWarnings(); wfDebug(__METHOD__ . " could not write to thumb path\n"); return $foreignUrl; } wfRestoreWarnings(); $knownThumbUrls[$sizekey] = $localUrl; $wgMemc->set($key, $knownThumbUrls, $this->apiThumbCacheExpiry); wfDebug(__METHOD__ . " got local thumb {$localUrl}, saving to cache \n"); return $localUrl; }
/** * Move a group of files to the deletion archive. * If no valid deletion archive is configured, this may either delete the * file or throw an exception, depending on the preference of the repository. * * @param array $sourceDestPairs Array of source/destination pairs. Each element * is a two-element array containing the source file path relative to the * public root in the first element, and the archive file path relative * to the deleted zone root in the second element. * @return FileRepoStatus */ function deleteBatch($sourceDestPairs) { $status = $this->newGood(); if (!$this->deletedDir) { throw new MWException(__METHOD__ . ': no valid deletion archive directory'); } /** * Validate filenames and create archive directories */ foreach ($sourceDestPairs as $pair) { list($srcRel, $archiveRel) = $pair; if (!$this->validateFilename($srcRel)) { throw new MWException(__METHOD__ . ':Validation error in $srcRel'); } if (!$this->validateFilename($archiveRel)) { throw new MWException(__METHOD__ . ':Validation error in $archiveRel'); } $archivePath = "{$this->deletedDir}/{$archiveRel}"; $archiveDir = dirname($archivePath); if (!is_dir($archiveDir)) { if (!wfMkdirParents($archiveDir)) { $status->fatal('directorycreateerror', $archiveDir); continue; } $this->initDeletedDir($archiveDir); } // Check if the archive directory is writable // This doesn't appear to work on NTFS if (!is_writable($archiveDir)) { $status->fatal('filedelete-archive-read-only', $archiveDir); } } if (!$status->ok) { // Abort early return $status; } /** * Move the files * We're now committed to returning an OK result, which will lead to * the files being moved in the DB also. */ foreach ($sourceDestPairs as $pair) { list($srcRel, $archiveRel) = $pair; $srcPath = "{$this->directory}/{$srcRel}"; $archivePath = "{$this->deletedDir}/{$archiveRel}"; $good = true; if (file_exists($archivePath)) { # A file with this content hash is already archived if (!@unlink($srcPath)) { $status->error('filedeleteerror', $srcPath); $good = false; } } else { if (!@rename($srcPath, $archivePath)) { $status->error('filerenameerror', $srcPath, $archivePath); $good = false; } else { @chmod($archivePath, 0644); } } if ($good) { $status->successCount++; } else { $status->failCount++; } } return $status; }