public function postProcess($action, $httpVars, $postProcessData) { if (isset($httpVars["simple_uploader"]) || isset($httpVars["xhr_uploader"])) { return; } /* If set resumeFileId and resumePartitionIndex, cross-session resume is requested. */ if (isset($httpVars["resumeFileId"]) && isset($httpVars["resumePartitionIndex"])) { header("HTTP/1.1 200 OK"); print "fileId: " . $httpVars["resumeFileId"] . "\n"; print "partitionIndex: " . $httpVars["resumePartitionIndex"]; return; } /*if (self::$skipDecoding) { }*/ if (isset($postProcessData["processor_result"]["ERROR"])) { if (isset($httpVars["lastPartition"]) && isset($httpVars["partitionCount"])) { /* we get the stream url (where all the partitions have been uploaded so far) */ $repository = ConfService::getRepository(); $dir = AJXP_Utils::decodeSecureMagic($httpVars["dir"]); $plugin = AJXP_PluginsService::findPlugin("access", $repository->getAccessType()); $streamData = $plugin->detectStreamWrapper(true); $destStreamURL = $streamData["protocol"] . "://" . $repository->getId() . $dir . "/"; if ($httpVars["partitionCount"] > 1) { /* we fetch the information that help us to construct the temp files name */ $fileId = $httpVars["fileId"]; $fileHash = md5($httpVars["fileName"]); /* deletion of all the partitions that have been uploaded */ for ($i = 0; $i < $httpVars["partitionCount"]; $i++) { if (file_exists($destStreamURL . "{$fileHash}.{$fileId}.{$i}")) { unlink($destStreamURL . "{$fileHash}.{$fileId}.{$i}"); } } } else { $fileName = $httpVars["fileName"]; unlink($destStreamURL . $fileName); } } echo "Error: " . $postProcessData["processor_result"]["ERROR"]["MESSAGE"]; return; } if (!isset($httpVars["partitionRealName"]) && !isset($httpVars["lastPartition"])) { return; } $repository = ConfService::getRepository(); $driver = ConfService::loadDriverForRepository($repository); if (!$repository->detectStreamWrapper(false)) { return false; } if ($httpVars["lastPartition"]) { $plugin = AJXP_PluginsService::findPlugin("access", $repository->getAccessType()); $streamData = $plugin->detectStreamWrapper(true); $dir = AJXP_Utils::decodeSecureMagic($httpVars["dir"]); $destStreamURL = $streamData["protocol"] . "://" . $repository->getId() . $dir . "/"; /* we check if the current file has a relative path (aka we want to upload an entire directory) */ AJXP_LOGGER::debug("Now dispatching relativePath dest:", $httpVars["relativePath"]); $subs = explode("/", $httpVars["relativePath"]); $userfile_name = array_pop($subs); $folderForbidden = false; $all_in_place = true; $partitions_length = 0; $fileId = $httpVars["fileId"]; $fileHash = md5($userfile_name); $partitionCount = $httpVars["partitionCount"]; $fileLength = $_POST["fileLength"]; if (self::$remote) { $partitions = array(); $newPartitions = array(); $index_first_partition = -1; $i = 0; do { $currentFileName = $driver->getFileNameToCopy(); $partitions[] = $driver->getNextFileToCopy(); if ($index_first_partition < 0 && strstr($currentFileName, $fileHash) != false) { $index_first_partition = $i; } else { if ($index_first_partition < 0) { $newPartitions[] = array_pop($partitions); } } } while ($driver->hasFilesToCopy()); } /* if partitionned */ if ($partitionCount > 1) { if (self::$remote) { for ($i = 0; $all_in_place && $i < $partitionCount; $i++) { $partition_file = "{$fileHash}.{$fileId}.{$i}"; if (strstr($partitions[$i]["name"], $partition_file) != false) { $partitions_length += filesize($partitions[$i]["tmp_name"]); } else { $all_in_place = false; } } } else { for ($i = 0; $all_in_place && $i < $partitionCount; $i++) { $partition_file = $destStreamURL . "{$fileHash}.{$fileId}.{$i}"; if (file_exists($partition_file)) { $partitions_length += filesize($partition_file); } else { $all_in_place = false; } } } } else { if (self::$remote) { if (strstr($newPartitions[count($newPartitions) - 1]["name"], $userfile_name) != false) { $partitions_length += filesize($newPartitions[count($newPartitions) - 1]["tmp_name"]); } } else { if (file_exists($destStreamURL . $userfile_name)) { $partitions_length += filesize($destStreamURL . $userfile_name); } } } if (!$all_in_place || $partitions_length != floatval($fileLength)) { echo "Error: Upload validation error!"; /* we delete all the uploaded partitions */ if ($httpVars["partitionCount"] > 1) { for ($i = 0; $i < $partitionCount; $i++) { if (file_exists($destStreamURL . "{$fileHash}.{$fileId}.{$i}")) { unlink($destStreamURL . "{$fileHash}.{$fileId}.{$i}"); } } } else { $fileName = $httpVars["partitionRealName"]; unlink($destStreamURL . $fileName); } return; } if (count($subs) > 0 && !self::$remote) { $curDir = ""; if (substr($curDir, -1) == "/") { $curDir = substr($curDir, 0, -1); } // Create the folder tree as necessary foreach ($subs as $key => $spath) { $messtmp = ""; $dirname = AJXP_Utils::decodeSecureMagic($spath, AJXP_SANITIZE_FILENAME); $dirname = substr($dirname, 0, ConfService::getCoreConf("NODENAME_MAX_LENGTH")); //$this->filterUserSelectionToHidden(array($dirname)); if (AJXP_Utils::isHidden($dirname)) { $folderForbidden = true; break; } if (file_exists($destStreamURL . "{$curDir}/{$dirname}")) { // if the folder exists, traverse $this->logDebug("{$curDir}/{$dirname} existing, traversing for {$userfile_name} out of", $httpVars["relativePath"]); $curDir .= "/" . $dirname; continue; } $this->logDebug($destStreamURL . $curDir); $dirMode = 0775; $chmodValue = $repository->getOption("CHMOD_VALUE"); if (isset($chmodValue) && $chmodValue != "") { $dirMode = octdec(ltrim($chmodValue, "0")); if ($dirMode & 0400) { $dirMode |= 0100; } // User is allowed to read, allow to list the directory if ($dirMode & 040) { $dirMode |= 010; } // Group is allowed to read, allow to list the directory if ($dirMode & 04) { $dirMode |= 01; } // Other are allowed to read, allow to list the directory } $old = umask(0); mkdir($destStreamURL . $curDir . "/" . $dirname, $dirMode); umask($old); $curDir .= "/" . $dirname; } } if (!$folderForbidden) { $fileId = $httpVars["fileId"]; $this->logDebug("Should now rebuild file!", $httpVars); // Now move the final file to the right folder // Currently the file is at the base of the current AJXP_LOGGER::debug("PartitionRealName", $destStreamURL . $httpVars["partitionRealName"]); $relPath = AJXP_Utils::decodeSecureMagic($httpVars["relativePath"]); $target = $destStreamURL; $target .= self::$remote ? basename($relPath) : $relPath; $current = $destStreamURL . basename($relPath); if ($httpVars["partitionCount"] > 1) { if (self::$remote) { $test = AJXP_Utils::getAjxpTmpDir() . "/" . $httpVars["partitionRealName"]; $newDest = fopen(AJXP_Utils::getAjxpTmpDir() . "/" . $httpVars["partitionRealName"], "w"); $newFile = array(); $length = 0; for ($i = 0, $count = count($partitions); $i < $count; $i++) { $currentFile = $partitions[$i]; $currentFileName = $currentFile["tmp_name"]; $part = fopen($currentFileName, "r"); while (!feof($part)) { $length += fwrite($newDest, fread($part, 4096)); } fclose($part); unlink($currentFileName); } $newFile["type"] = $partitions[0]["type"]; $newFile["name"] = $httpVars["partitionRealName"]; $newFile["error"] = 0; $newFile["size"] = $length; $newFile["tmp_name"] = AJXP_Utils::getAjxpTmpDir() . "/" . $httpVars["partitionRealName"]; $newFile["destination"] = $partitions[0]["destination"]; $newPartitions[] = $newFile; } else { $newDest = fopen($destStreamURL . $httpVars["partitionRealName"], "w"); $fileHash = md5($httpVars["partitionRealName"]); for ($i = 0; $i < $httpVars["partitionCount"]; $i++) { $part = fopen($destStreamURL . "{$fileHash}.{$fileId}.{$i}", "r"); while (!feof($part)) { fwrite($newDest, fread($part, 4096)); } fclose($part); unlink($destStreamURL . "{$fileHash}.{$fileId}.{$i}"); } } fclose($newDest); } if (!self::$remote) { $err = copy($current, $target); } else { for ($i = 0, $count = count($newPartitions); $i < $count; $i++) { $driver->storeFileToCopy($newPartitions[$i]); } } if ($err !== false) { if (!self::$remote) { unlink($current); } AJXP_Controller::applyHook("node.change", array(null, new AJXP_Node($target), false)); } else { if ($current == $target) { AJXP_Controller::applyHook("node.change", array(null, new AJXP_Node($target), false)); } } } else { // Remove the file, as it should not have been uploaded! if (!self::$remote) { unlink($current); } } } }
public function preProcess($action, &$httpVars, &$fileVars) { if (isset($httpVars["simple_uploader"]) || isset($httpVars["xhr_uploader"])) { return; } $repository = ConfService::getRepository(); $driver = ConfService::loadDriverForRepository($repository); if (method_exists($driver, "storeFileToCopy")) { self::$remote = true; } if ($repository->detectStreamWrapper(false)) { $plugin = AJXP_PluginsService::findPlugin("access", $repository->getAccessType()); $streamData = $plugin->detectStreamWrapper(true); if ($streamData["protocol"] == "ajxp.ftp" || $streamData["protocol"] == "ajxp.remotefs") { $this->logDebug("Skip decoding"); self::$skipDecoding = true; } $this->logDebug("Stream ", $streamData); self::$wrapperIsRemote = call_user_func(array($streamData["classname"], "isRemote")); } $this->logDebug("Jumploader HttpVars", $httpVars); $this->logDebug("Jumploader FileVars", $fileVars); $httpVars["dir"] = base64_decode(str_replace(" ", "+", $httpVars["dir"])); $index = $httpVars["partitionIndex"]; $realName = $fileVars["userfile_0"]["name"]; /* if fileId is not set, request for cross-session resume (only if the protocol is not ftp)*/ if (!isset($httpVars["fileId"])) { $this->logDebug("Trying Cross-Session Resume request"); $plugin = AJXP_PluginsService::findPlugin("access", $repository->getAccessType()); $streamData = $plugin->detectStreamWrapper(true); $dir = AJXP_Utils::decodeSecureMagic($httpVars["dir"]); $destStreamURL = $streamData["protocol"] . "://" . $repository->getId() . $dir; $fileHash = md5($httpVars["fileName"]); if (!self::$remote) { $resumeIndexes = array(); $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($destStreamURL)); $it->setMaxDepth(0); while ($it->valid()) { if (!$it->isDot()) { $subPathName = $it->getSubPathName(); AJXP_LOGGER::debug("Iterator SubPathName: " . $it->getSubPathName()); if (strstr($subPathName, $fileHash) != false) { $explodedSubPathName = explode('.', $subPathName); $resumeFileId = $explodedSubPathName[1]; $resumeIndexes[] = $explodedSubPathName[2]; $this->logDebug("Current Index: " . $explodedSubPathName[2]); } } $it->next(); } /* no valid temp file found. return. */ if (empty($resumeIndexes)) { $this->logDebug("No Cross-Session Resume request"); return; } AJXP_LOGGER::debug("ResumeFileID: " . $resumeFileId); AJXP_LOGGER::debug("Max Resume Index: " . max($resumeIndexes)); $nextResumeIndex = max($resumeIndexes) + 1; AJXP_LOGGER::debug("Next Resume Index: " . $nextResumeIndex); if (isset($resumeFileId)) { $this->logDebug("ResumeFileId is set. Returning values: fileId: " . $resumeFileId . ", partitionIndex: " . $nextResumeIndex); $httpVars["resumeFileId"] = $resumeFileId; $httpVars["resumePartitionIndex"] = $nextResumeIndex; } } return; } /* if the file has to be partitioned */ if (isset($httpVars["partitionCount"]) && intval($httpVars["partitionCount"]) > 1) { $this->logDebug("Partitioned upload"); $fileId = $httpVars["fileId"]; $fileHash = md5($realName); /* In order to enable cross-session resume, temp files must not depend on session. * Now named after and md5() of the original file name. */ $this->logDebug("Filename: " . $realName . ", File hash: " . $fileHash); $fileVars["userfile_0"]["name"] = "{$fileHash}.{$fileId}.{$index}"; $httpVars["lastPartition"] = false; } else { /* * If we wan to upload a folderUpload to folderServer * Temporarily,put all files in this folder to folderServer. * But a same file name may be existed in folderServer, * this can cause error of uploading. * * We rename this file by his relativePath. At the postProcess session, we will use this name * to copy to right location * */ $file_tmp_md5 = md5($httpVars["relativePath"]); $fileVars["userfile_0"]["name"] = $file_tmp_md5; } /* if we received the last partition */ if (intval($index) == intval($httpVars["partitionCount"]) - 1) { $httpVars["lastPartition"] = true; $httpVars["partitionRealName"] = $realName; } }
public function postProcess($action, $httpVars, $postProcessData) { if (isset($httpVars["simple_uploader"]) || isset($httpVars["xhr_uploader"])) { return; } if (self::$skipDecoding) { } if (!isset($httpVars["partitionRealName"]) && !isset($httpVars["checkRelativePath"])) { return; } $repository = ConfService::getRepository(); if (!$repository->detectStreamWrapper(false)) { return false; } $plugin = AJXP_PluginsService::findPlugin("access", $repository->getAccessType()); $streamData = $plugin->detectStreamWrapper(true); $dir = AJXP_Utils::decodeSecureMagic($httpVars["dir"]); $destStreamURL = $streamData["protocol"] . "://" . $repository->getId() . $dir . "/"; if (isset($httpVars["partitionRealName"])) { $count = intval($httpVars["partitionCount"]); $index = intval($httpVars["partitionIndex"]); $fileId = $httpVars["fileId"]; $clientId = $httpVars["ajxp_sessid"]; AJXP_Logger::debug("Should now rebuild file!", $httpVars); $newDest = fopen($destStreamURL . $httpVars["partitionRealName"], "w"); AJXP_LOGGER::debug("PartitionRealName", $destStreamURL . $httpVars["partitionRealName"]); for ($i = 0; $i < $count; $i++) { $part = fopen($destStreamURL . "{$clientId}.{$fileId}.{$i}", "r"); while (!feof($part)) { fwrite($newDest, fread($part, 4096)); } fclose($part); unlink($destStreamURL . "{$clientId}.{$fileId}.{$i}"); } fclose($newDest); } if (isset($httpVars["checkRelativePath"])) { AJXP_LOGGER::debug("Now dispatching relativePath dest:", $httpVars["relativePath"]); $subs = explode("/", $httpVars["relativePath"]); $userfile_name = array_pop($subs); $subpath = ""; $curDir = ""; // remove trailing slash from current dir if we've got subdirs if (count($subs) > 0) { if (substr($curDir, -1) == "/") { $curDir = substr($curDir, 0, -1); } $folderForbidden = false; // Create the folder tree as necessary foreach ($subs as $key => $spath) { $messtmp = ""; $dirname = AJXP_Utils::decodeSecureMagic($spath, AJXP_SANITIZE_HTML_STRICT); $dirname = substr($dirname, 0, ConfService::getCoreConf("NODENAME_MAX_LENGTH")); //$this->filterUserSelectionToHidden(array($dirname)); if (AJXP_Utils::isHidden($dirname)) { $folderForbidden = true; break; } if (file_exists($destStreamURL . "{$curDir}/{$dirname}")) { // if the folder exists, traverse AJXP_Logger::debug("{$curDir}/{$dirname} existing, traversing for {$userfile_name} out of", $httpVars["relativePath"]); $curDir .= "/" . $dirname; continue; } AJXP_Logger::debug($destStreamURL . $curDir); $dirMode = 0775; $chmodValue = $repository->getOption("CHMOD_VALUE"); if (isset($chmodValue) && $chmodValue != "") { $dirMode = octdec(ltrim($chmodValue, "0")); if ($dirMode & 0400) { $dirMode |= 0100; } // User is allowed to read, allow to list the directory if ($dirMode & 040) { $dirMode |= 010; } // Group is allowed to read, allow to list the directory if ($dirMode & 04) { $dirMode |= 01; } // Other are allowed to read, allow to list the directory } $old = umask(0); mkdir($destStreamURL . $curDir . "/" . $dirname, $dirMode); umask($old); $curDir .= "/" . $dirname; } // Now move the final file to the right folder // Currently the file is at the base of the current $relPath = AJXP_Utils::decodeSecureMagic($httpVars["relativePath"]); $current = $destStreamURL . basename($relPath); $target = $destStreamURL . $relPath; if (!$folderForbidden) { $err = copy($current, $target); if ($err !== false) { unlink($current); } } else { // Remove the file, as it should not have been uploaded! unlink($current); } } } }