/** Cypher the publiclet object data and write to disk. * @param Array $data The publiclet data array to write The data array must have the following keys: - DRIVER The driver used to get the file's content - OPTIONS The driver options to be successfully constructed (usually, the user and password) - FILE_PATH The path to the file's content - PASSWORD If set, the written publiclet will ask for this password before sending the content - ACTION If set, action to perform - USER If set, the AJXP user - EXPIRE_TIME If set, the publiclet will deny downloading after this time, and probably self destruct. * - AUTHOR_WATCH If set, will post notifications for the publiclet author each time the file is loaded * @param AbstractAccessDriver $accessDriver * @param Repository $repository * @return array An array containing the hash (0) and the generated url (1) */ public function writePubliclet(&$data, $accessDriver, $repository) { $downloadFolder = ConfService::getCoreConf("PUBLIC_DOWNLOAD_FOLDER"); if (!is_dir($downloadFolder)) { return "ERROR : Public URL folder does not exist!"; } if (!function_exists("mcrypt_create_iv")) { return "ERROR : MCrypt must be installed to use publiclets!"; } $this->initPublicFolder($downloadFolder); $data["PLUGIN_ID"] = $accessDriver->getId(); $data["BASE_DIR"] = $accessDriver->getBaseDir(); //$data["REPOSITORY"] = $repository; if (AuthService::usersEnabled()) { $data["OWNER_ID"] = AuthService::getLoggedUser()->getId(); } $storeCreds = false; if ($repository->getOption("META_SOURCES")) { $options["META_SOURCES"] = $repository->getOption("META_SOURCES"); foreach ($options["META_SOURCES"] as $metaSource) { if (isset($metaSource["USE_SESSION_CREDENTIALS"]) && $metaSource["USE_SESSION_CREDENTIALS"] === true) { $storeCreds = true; break; } } } if ($storeCreds || $accessDriver->hasMixin("credentials_consumer")) { $cred = AJXP_Safe::tryLoadingCredentialsFromSources(array(), $repository); if (isset($cred["user"]) && isset($cred["password"])) { $data["SAFE_USER"] = $cred["user"]; $data["SAFE_PASS"] = $cred["password"]; } } // Force expanded path in publiclet $copy = clone $repository; $copy->addOption("PATH", $repository->getOption("PATH")); $data["REPOSITORY"] = $copy; if ($data["ACTION"] == "") { $data["ACTION"] = "download"; } // Create a random key $data["FINAL_KEY"] = md5(mt_rand() . time()); // Cypher the data with a random key $outputData = serialize($data); // Hash the data to make sure it wasn't modified $hash = $this->computeHash($outputData, $downloadFolder); // md5($outputData); $outputData = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $hash, $outputData, MCRYPT_MODE_ECB)); $fileData = "<" . "?" . "php \n" . ' require_once("' . str_replace("\\", "/", AJXP_INSTALL_PATH) . '/publicLet.inc.php"); ' . "\n" . ' $id = str_replace(".php", "", basename(__FILE__)); ' . "\n" . ' $cypheredData = base64_decode("' . $outputData . '"); ' . "\n" . ' $inputData = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $id, $cypheredData, MCRYPT_MODE_ECB), "\\0"); ' . "\n" . ' if (!ShareCenter::checkHash($inputData, $id)) { header("HTTP/1.0 401 Not allowed, script was modified"); exit(); } ' . "\n" . ' // Ok extract the data ' . "\n" . ' $data = unserialize($inputData); ShareCenter::loadPubliclet($data); '; if (@file_put_contents($downloadFolder . "/" . $hash . ".php", $fileData) === FALSE) { return "Can't write to PUBLIC URL"; } @chmod($downloadFolder . "/" . $hash . ".php", 0755); PublicletCounter::reset($hash); $url = $this->buildPublicletLink($hash); $this->logInfo("New Share", array("file" => "'" . $copy->display . ":/" . $data['FILE_PATH'] . "'", "url" => $url, "expiration" => $data['EXPIRE_TIME'], "limit" => $data['DOWNLOAD_LIMIT'], "repo_uuid" => $copy->uuid)); AJXP_Controller::applyHook("node.share.create", array('type' => 'file', 'repository' => &$copy, 'accessDriver' => &$accessDriver, 'data' => &$data, 'url' => $url)); return array($hash, $url); }
/** Cypher the publiclet object data and write to disk. * @param array $data The publiclet data array to write * The data array must have the following keys: * - DRIVER The driver used to get the file's content * - OPTIONS The driver options to be successfully constructed (usually, the user and password) * - FILE_PATH The path to the file's content * - PASSWORD If set, the written publiclet will ask for this password before sending the content * - ACTION If set, action to perform * - USER If set, the AJXP user * - EXPIRE_TIME If set, the publiclet will deny downloading after this time, and probably self destruct. * - AUTHOR_WATCH If set, will post notifications for the publiclet author each time the file is loaded * @param AbstractAccessDriver $accessDriver * @param Repository $repository * @param ShareStore $shareStore * @param PublicAccessManager $publicAccessManager * @return string|array An array containing the hash (0) and the generated url (1) */ public function writePubliclet(&$data, $accessDriver, $repository, $shareStore, $publicAccessManager) { $downloadFolder = $publicAccessManager->getPublicDownloadFolder(); $publicAccessManager->initFolder(); if (!is_dir($downloadFolder)) { return "ERROR : Public URL folder does not exist!"; } if (!function_exists("mcrypt_create_iv")) { return "ERROR : MCrypt must be installed to use publiclets!"; } $data["PLUGIN_ID"] = $accessDriver->getId(); $data["BASE_DIR"] = $accessDriver->getBaseDir(); //$data["REPOSITORY"] = $repository; if (AuthService::usersEnabled()) { $data["OWNER_ID"] = AuthService::getLoggedUser()->getId(); } $shareStore->storeSafeCredentialsIfNeeded($data, $accessDriver, $repository); // Force expanded path in publiclet $copy = clone $repository; $copy->addOption("PATH", $repository->getOption("PATH")); $data["REPOSITORY"] = $copy; if ($data["ACTION"] == "") { $data["ACTION"] = "download"; } try { $hash = $shareStore->storeShare($repository->getId(), $data, "publiclet"); } catch (Exception $e) { return $e->getMessage(); } $shareStore->resetDownloadCounter($hash, AuthService::getLoggedUser()->getId()); $url = $publicAccessManager->buildPublicLink($hash); AJXP_Logger::log2(LOG_LEVEL_INFO, __CLASS__, "New Share", array("file" => "'" . $copy->display . ":/" . $data['FILE_PATH'] . "'", "files" => "'" . $copy->display . ":/" . $data['FILE_PATH'] . "'", "url" => $url, "expiration" => $data['EXPIRE_TIME'], "limit" => $data['DOWNLOAD_LIMIT'], "repo_uuid" => $copy->uuid)); AJXP_Controller::applyHook("node.share.create", array('type' => 'file', 'repository' => &$copy, 'accessDriver' => &$accessDriver, 'data' => &$data, 'url' => $url)); return array($hash, $url); }
/** Cypher the publiclet object data and write to disk. * @param Array $data The publiclet data array to write The data array must have the following keys: - DRIVER The driver used to get the file's content - OPTIONS The driver options to be successfully constructed (usually, the user and password) - FILE_PATH The path to the file's content - PASSWORD If set, the written publiclet will ask for this password before sending the content - ACTION If set, action to perform - USER If set, the AJXP user - EXPIRE_TIME If set, the publiclet will deny downloading after this time, and probably self destruct. * @param AbstractAccessDriver $accessDriver * @param Repository $repository * @return the URL to the downloaded file */ function writePubliclet($data, $accessDriver, $repository) { $downloadFolder = ConfService::getCoreConf("PUBLIC_DOWNLOAD_FOLDER"); if (!is_dir($downloadFolder)) { return "ERROR : Public URL folder does not exist!"; } if (!function_exists("mcrypt_create_iv")) { return "ERROR : MCrypt must be installed to use publiclets!"; } $this->initPublicFolder($downloadFolder); $data["PLUGIN_ID"] = $accessDriver->getId(); $data["BASE_DIR"] = $accessDriver->getBaseDir(); $data["REPOSITORY"] = $repository; if (AuthService::usersEnabled()) { $data["OWNER_ID"] = AuthService::getLoggedUser()->getId(); } if ($accessDriver->hasMixin("credentials_consumer")) { $cred = AJXP_Safe::tryLoadingCredentialsFromSources(array(), $repository); if (isset($cred["user"]) && isset($cred["password"])) { $data["SAFE_USER"] = $cred["user"]; $data["SAFE_PASS"] = $cred["password"]; } } // Force expanded path in publiclet $data["REPOSITORY"]->addOption("PATH", $repository->getOption("PATH")); if ($data["ACTION"] == "") { $data["ACTION"] = "download"; } // Create a random key $data["FINAL_KEY"] = md5(mt_rand() . time()); // Cypher the data with a random key $outputData = serialize($data); // Hash the data to make sure it wasn't modified $hash = md5($outputData); // The initialisation vector is only required to avoid a warning, as ECB ignore IV $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); // We have encoded as base64 so if we need to store the result in a database, it can be stored in text column $outputData = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $hash, $outputData, MCRYPT_MODE_ECB, $iv)); // Okay, write the file: $fileData = "<" . "?" . "php \n" . ' require_once("' . str_replace("\\", "/", AJXP_INSTALL_PATH) . '/publicLet.inc.php"); ' . "\n" . ' $id = str_replace(".php", "", basename(__FILE__)); ' . "\n" . ' $cypheredData = base64_decode("' . $outputData . '"); ' . "\n" . ' $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); ' . "\n" . ' $inputData = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $id, $cypheredData, MCRYPT_MODE_ECB, $iv), "\\0"); ' . "\n" . ' if (md5($inputData) != $id) { header("HTTP/1.0 401 Not allowed, script was modified"); exit(); } ' . "\n" . ' // Ok extract the data ' . "\n" . ' $data = unserialize($inputData); ShareCenter::loadPubliclet($data); ?' . '>'; if (@file_put_contents($downloadFolder . "/" . $hash . ".php", $fileData) === FALSE) { return "Can't write to PUBLIC URL"; } @chmod($downloadFolder . "/" . $hash . ".php", 0755); PublicletCounter::reset($hash); return $this->buildPublicletLink($hash); }