/** * Repacks exported document from Google.Drive, which has wrong order files in archive to show preview * in Google.Viewer. In Google.Viewer document should have file '[Content_Types].xml' on first position in archive. * @param FileData $fileData * @return FileData * @throws IO\FileNotFoundException * @throws IO\InvalidPathException * @internal */ public function repackDocument(FileData $fileData) { if (!extension_loaded('zip')) { return null; } if (!TypeFile::isDocument($fileData->getName())) { return null; } $file = new IO\File($fileData->getSrc()); if (!$file->isExists() || $file->getSize() > 15 * 1024 * 1024) { return null; } unset($file); $ds = DIRECTORY_SEPARATOR; $targetDir = \CTempFile::getDirectoryName(2, 'disk_repack' . $ds . md5(uniqid('di', true))); checkDirPath($targetDir); $targetDir = IO\Path::normalize($targetDir) . $ds; $zipOrigin = new \ZipArchive(); if (!$zipOrigin->open($fileData->getSrc())) { return null; } if ($zipOrigin->getNameIndex(0) === '[Content_Types].xml') { $zipOrigin->close(); return null; } if (!$zipOrigin->extractTo($targetDir)) { $zipOrigin->close(); return null; } $zipOrigin->close(); unset($zipOrigin); if (is_dir($targetDir) !== true) { return null; } $newName = md5(uniqid('di', true)); $newFilepath = $targetDir . '..' . $ds . $newName; $repackedZip = new \ZipArchive(); if (!$repackedZip->open($newFilepath, \ZipArchive::CREATE)) { return null; } $source = realpath($targetDir); $repackedZip->addFile($source . $ds . '[Content_Types].xml', '[Content_Types].xml'); $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); foreach ($files as $file) { if ($file->getBasename() === '[Content_Types].xml') { continue; } $file = str_replace('\\', '/', $file); $file = realpath($file); if (is_dir($file) === true) { $repackedZip->addEmptyDir(str_replace('\\', '/', str_replace($source . $ds, '', $file . $ds))); } elseif (is_file($file) === true) { $repackedZip->addFile($file, str_replace('\\', '/', str_replace($source . $ds, '', $file))); } } $repackedZip->close(); $newFileData = new FileData(); $newFileData->setSrc($newFilepath); return $newFileData; }
/** * @param $matches * @return string * @throws \Bitrix\Main\IO\FileNotFoundException */ protected function getReplacedImageCid($matches) { $src = $matches[3]; if ($src == "") { return $matches[0]; } if (array_key_exists($src, $this->filesReplacedFromBody)) { $uid = $this->filesReplacedFromBody[$src]["ID"]; return $matches[1] . $matches[2] . "cid:" . $uid . $matches[4] . $matches[5]; } $io = \CBXVirtualIo::GetInstance(); $filePath = $io->GetPhysicalName(\Bitrix\Main\Application::getDocumentRoot() . $src); if (!File::isFileExists($filePath)) { return $matches[0]; } foreach ($this->attachment as $attach) { if ($filePath == $attach['PATH']) { return $matches[1] . $matches[2] . "cid:" . $attach['ID'] . $matches[4] . $matches[5]; } } if ($this->settingMaxFileSize > 0) { $fileIoObject = new File($filePath); if ($fileIoObject->getSize() > $this->settingMaxFileSize) { return $matches[0]; } } $aImage = \CFile::GetImageSize($filePath, true); if (!is_array($aImage)) { return $matches[0]; } if (function_exists("image_type_to_mime_type")) { $contentType = image_type_to_mime_type($aImage[2]); } else { $contentType = $this->imageTypeToMimeType($aImage[2]); } $uid = uniqid(md5($src)); $this->filesReplacedFromBody[$src] = array("SRC" => $src, "PATH" => $filePath, "CONTENT_TYPE" => $contentType, "NAME" => bx_basename($src), "ID" => $uid); return $matches[1] . $matches[2] . "cid:" . $uid . $matches[4] . $matches[5]; }
function SaveFile($arFile, $strSavePath, $bForceMD5 = false, $bSkipExt = false) { $strFileName = GetFileName($arFile["name"]); /* filename.gif */ if (isset($arFile["del"]) && $arFile["del"] != '') { CFile::DoDelete($arFile["old_file"]); if ($strFileName == '') { return "NULL"; } } if ($arFile["name"] == '') { if (isset($arFile["description"]) && intval($arFile["old_file"]) > 0) { CFile::UpdateDesc($arFile["old_file"], $arFile["description"]); } return false; } if (isset($arFile["content"])) { if (!isset($arFile["size"])) { $arFile["size"] = CUtil::BinStrlen($arFile["content"]); } } else { try { $file = new IO\File($arFile["tmp_name"]); $arFile["size"] = $file->getSize(); } catch (IO\IoException $e) { $arFile["size"] = 0; } } $arFile["ORIGINAL_NAME"] = $strFileName; //translit, replace unsafe chars, etc. $strFileName = self::transformName($strFileName, $bForceMD5, $bSkipExt); //transformed name must be valid, check disk quota, etc. if (self::validateFile($strFileName, $arFile) !== "") { return false; } if ($arFile["type"] == "image/pjpeg" || $arFile["type"] == "image/jpg") { $arFile["type"] = "image/jpeg"; } $bExternalStorage = false; foreach (GetModuleEvents("main", "OnFileSave", true) as $arEvent) { if (ExecuteModuleEventEx($arEvent, array(&$arFile, $strFileName, $strSavePath, $bForceMD5, $bSkipExt))) { $bExternalStorage = true; break; } } if (!$bExternalStorage) { $upload_dir = COption::GetOptionString("main", "upload_dir", "upload"); $io = CBXVirtualIo::GetInstance(); if ($bForceMD5 != true && COption::GetOptionString("main", "save_original_file_name", "N") == "Y") { $dir_add = ''; $i = 0; while (true) { $dir_add = substr(md5(uniqid("", true)), 0, 3); if (!$io->FileExists($_SERVER["DOCUMENT_ROOT"] . "/" . $upload_dir . "/" . $strSavePath . "/" . $dir_add . "/" . $strFileName)) { break; } if ($i >= 25) { $j = 0; while (true) { $dir_add = substr(md5(mt_rand()), 0, 3) . "/" . substr(md5(mt_rand()), 0, 3); if (!$io->FileExists($_SERVER["DOCUMENT_ROOT"] . "/" . $upload_dir . "/" . $strSavePath . "/" . $dir_add . "/" . $strFileName)) { break; } if ($j >= 25) { $dir_add = substr(md5(mt_rand()), 0, 3) . "/" . md5(mt_rand()); break; } $j++; } break; } $i++; } if (substr($strSavePath, -1, 1) != "/") { $strSavePath .= "/" . $dir_add; } else { $strSavePath .= $dir_add . "/"; } } else { $strFileExt = $bSkipExt == true || ($ext = GetFileExtension($strFileName)) == '' ? '' : "." . $ext; while (true) { if (substr($strSavePath, -1, 1) != "/") { $strSavePath .= "/" . substr($strFileName, 0, 3); } else { $strSavePath .= substr($strFileName, 0, 3) . "/"; } if (!$io->FileExists($_SERVER["DOCUMENT_ROOT"] . "/" . $upload_dir . "/" . $strSavePath . "/" . $strFileName)) { break; } //try the new name $strFileName = md5(uniqid("", true)) . $strFileExt; } } $arFile["SUBDIR"] = $strSavePath; $arFile["FILE_NAME"] = $strFileName; $strDirName = $_SERVER["DOCUMENT_ROOT"] . "/" . $upload_dir . "/" . $strSavePath . "/"; $strDbFileNameX = $strDirName . $strFileName; $strPhysicalFileNameX = $io->GetPhysicalName($strDbFileNameX); CheckDirPath($strDirName); if (is_set($arFile, "content")) { $f = fopen($strPhysicalFileNameX, "ab"); if (!$f) { return false; } if (fwrite($f, $arFile["content"]) === false) { return false; } fclose($f); } elseif (!copy($arFile["tmp_name"], $strPhysicalFileNameX) && !move_uploaded_file($arFile["tmp_name"], $strPhysicalFileNameX)) { CFile::DoDelete($arFile["old_file"]); return false; } if (isset($arFile["old_file"])) { CFile::DoDelete($arFile["old_file"]); } @chmod($strPhysicalFileNameX, BX_FILE_PERMISSIONS); //flash is not an image $flashEnabled = !CFile::IsImage($arFile["ORIGINAL_NAME"], $arFile["type"]); $imgArray = CFile::GetImageSize($strDbFileNameX, false, $flashEnabled); if (is_array($imgArray)) { $arFile["WIDTH"] = $imgArray[0]; $arFile["HEIGHT"] = $imgArray[1]; if ($imgArray[2] == IMAGETYPE_JPEG) { $exifData = CFile::ExtractImageExif($io->GetPhysicalName($strDbFileNameX)); if ($exifData && isset($exifData['Orientation'])) { //swap width and height if ($exifData['Orientation'] >= 5 && $exifData['Orientation'] <= 8) { $arFile["WIDTH"] = $imgArray[1]; $arFile["HEIGHT"] = $imgArray[0]; } $properlyOriented = CFile::ImageHandleOrientation($exifData['Orientation'], $io->GetPhysicalName($strDbFileNameX)); if ($properlyOriented) { $jpgQuality = intval(COption::GetOptionString('main', 'image_resize_quality', '95')); if ($jpgQuality <= 0 || $jpgQuality > 100) { $jpgQuality = 95; } imagejpeg($properlyOriented, $io->GetPhysicalName($strDbFileNameX), $jpgQuality); } } } } else { $arFile["WIDTH"] = 0; $arFile["HEIGHT"] = 0; } } if ($arFile["WIDTH"] == 0 || $arFile["HEIGHT"] == 0) { //mock image because we got false from CFile::GetImageSize() if (strpos($arFile["type"], "image/") === 0) { $arFile["type"] = "application/octet-stream"; } } if ($arFile["type"] == '' || !is_string($arFile["type"])) { $arFile["type"] = "application/octet-stream"; } /****************************** QUOTA ******************************/ if (COption::GetOptionInt("main", "disk_space") > 0) { CDiskQuota::updateDiskQuota("file", $arFile["size"], "insert"); } /****************************** QUOTA ******************************/ $NEW_IMAGE_ID = CFile::DoInsert(array("HEIGHT" => $arFile["HEIGHT"], "WIDTH" => $arFile["WIDTH"], "FILE_SIZE" => $arFile["size"], "CONTENT_TYPE" => $arFile["type"], "SUBDIR" => $arFile["SUBDIR"], "FILE_NAME" => $arFile["FILE_NAME"], "MODULE_ID" => $arFile["MODULE_ID"], "ORIGINAL_NAME" => $arFile["ORIGINAL_NAME"], "DESCRIPTION" => isset($arFile["description"]) ? $arFile["description"] : '', "HANDLER_ID" => isset($arFile["HANDLER_ID"]) ? $arFile["HANDLER_ID"] : '', "EXTERNAL_ID" => isset($arFile["external_id"]) ? $arFile["external_id"] : md5(mt_rand()))); CFile::CleanCache($NEW_IMAGE_ID); return $NEW_IMAGE_ID; }
/** * Fix for Google. It does not get in metadata real size of empty file. * @param Entry $entry * @param Document\FileData $fileData * @return bool * @throws IO\FileNotFoundException * @throws \Bitrix\Main\SystemException */ protected function uploadEmptyFileFromGoogle(Entry $entry, Document\FileData $fileData) { $tmpFile = $fileData->getSrc(); $downloadedContentSize = $entry->getDownloadedContentSize(); $startRange = $downloadedContentSize; //fix for Google. It doesn't get in metadata real size of empty file. if (!$this->documentHandler->downloadFile($fileData)) { $this->errorCollection->add($this->documentHandler->getErrors()); return false; } $realFile = new IO\File($tmpFile); $contentSize = $realFile->getSize(); $entry->setContentSize($contentSize); $chunkSize = $contentSize - $downloadedContentSize; $uploadFileManager = new Bitrix24Disk\UploadFileManager(); $uploadFileManager->setTmpFileClass(TmpFile::className())->setUser($this->documentHandler->getUserId())->setFileSize($contentSize)->setContentRange(array($startRange, $startRange + $chunkSize - 1)); $tmpFileArray = \CFile::makeFileArray($tmpFile); if (!$uploadFileManager->upload($fileData->getId(), $tmpFileArray)) { $this->errorCollection->add($uploadFileManager->getErrors()); return false; } $entry->linkTmpFile(TmpFile::load(array('=TOKEN' => $uploadFileManager->getToken()))); return $entry->increaseDownloadedContentSize($chunkSize); }