uawdijnntqw1x1x1
IP : 216.73.216.163
Hostname : yjpwxulqtt
Kernel : Linux yjpwxulqtt 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,exec,system,passthru,shell_exec,proc_open,popen
OS : Linux
PATH:
/
home
/
user
/
web
/
pansionat-v-yaroslavle.ru
/
public_html
/
70645
/
..
/
331ab
/
.
/
clouds.tar
/
/
lang/ru/install/index.php000064400000000660150241560060011402 0ustar00<? $MESS["CLO_MODULE_NAME"] = "Облачные хранилища"; $MESS["CLO_MODULE_DESCRIPTION"] = "Модуль поддержки облачных хранилищ файлов."; $MESS["CLO_INSTALL_TITLE"] = "Установка модуля поддержки облачных хранилищ"; $MESS["CLO_UNINSTALL_TITLE"] = "Деинсталляция модуля поддержки облачных хранилищ"; ?>lang/ru/install/step1.php000064400000000165150241560060011327 0ustar00<? $MESS["CLO_INSTALL"] = "Установка модуля поддержки облачных хранилищ."; ?>lang/ru/classes/general/storage_service_clodo.php000064400000000360150241560060016240 0ustar00<? $MESS["CLO_STORAGE_CLODO_EDIT_USER"] = "Имя пользователя (API user)"; $MESS["CLO_STORAGE_CLODO_EDIT_KEY"] = "Ключ доступа (API key)"; $MESS["CLO_STORAGE_CLODO_EDIT_HOST"] = "Имя сервера (API host)"; ?>lang/ru/classes/general/storage_upload.php000064400000000151150241560060014702 0ustar00<? $MESS["CLO_STORAGE_UPLOAD_ERROR"] = "Ошибка загрузки части файла: #errno#"; ?>lang/ru/classes/general/storage_service_s3.php000064400000001765150241560060015477 0ustar00<? $MESS["CLO_STORAGE_S3_XML_PARSE_ERROR"] = "нераспознанный ответ службы (ошибка ##errno#)"; $MESS["CLO_STORAGE_S3_XML_ERROR"] = "ошибка службы: #errmsg#"; $MESS["CLO_STORAGE_S3_EMPTY_ACCESS_KEY"] = "Не задан ключ доступа."; $MESS["CLO_STORAGE_S3_EMPTY_SECRET_KEY"] = "Не задан секретный ключ."; $MESS["CLO_STORAGE_S3_EDIT_ACCESS_KEY"] = "Ключ доступа"; $MESS["CLO_STORAGE_S3_EDIT_SECRET_KEY"] = "Секретный ключ"; $MESS["CLO_STORAGE_S3_EDIT_HELP"] = "Для начала использования необходимо зарегистрироваться в <a href=\"http://aws.amazon.com/s3/\">Amazon</a> и активировать доступ к S3. Ключ доступа и секретный ключ к нему можно получить на странице <a href=\"https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=access-key\">Security Credentials</a>."; ?>lang/ru/classes/general/storage_service_openstack.php000064400000001442150241560060017131 0ustar00<? $MESS["CLO_STORAGE_OPENSTACK_EMPTY_HOST"] = "Не задано имя сервера."; $MESS["CLO_STORAGE_OPENSTACK_EMPTY_USER"] = "Не задано имя пользователя."; $MESS["CLO_STORAGE_OPENSTACK_EMPTY_KEY"] = "Не задан ключ доступа."; $MESS["CLO_STORAGE_OPENSTACK_ERROR_GET_TOKEN"] = "Ошибка авторизации. Проверьте правильность введенных настроек."; $MESS["CLO_STORAGE_OPENSTACK_EDIT_USER"] = "Имя пользователя (API user)"; $MESS["CLO_STORAGE_OPENSTACK_EDIT_KEY"] = "Ключ доступа (API key)"; $MESS["CLO_STORAGE_OPENSTACK_EDIT_HOST"] = "Имя сервера (API host)"; $MESS["CLO_STORAGE_OPENSTACK_FORCE_HTTP"] = "Всегда использовать протокол http"; ?>lang/ru/classes/general/storage_service_google.php000064400000002317150241560060016420 0ustar00<? $MESS["CLO_STORAGE_GOOGLE_XML_PARSE_ERROR"] = "нераспознанный ответ службы (ошибка ##errno#)"; $MESS["CLO_STORAGE_GOOGLE_XML_ERROR"] = "ошибка службы: #errmsg#"; $MESS["CLO_STORAGE_GOOGLE_EMPTY_ACCESS_KEY"] = "Не задан ключ доступа."; $MESS["CLO_STORAGE_GOOGLE_EMPTY_SECRET_KEY"] = "Не задан секретный ключ."; $MESS["CLO_STORAGE_GOOGLE_EMPTY_PROJECT_ID"] = "Не задан идентификатор проекта."; $MESS["CLO_STORAGE_GOOGLE_EDIT_PROJECT_ID"] = "Идентификатор проекта"; $MESS["CLO_STORAGE_GOOGLE_EDIT_ACCESS_KEY"] = "Ключ доступа"; $MESS["CLO_STORAGE_GOOGLE_EDIT_SECRET_KEY"] = "Секретный ключ"; $MESS["CLO_STORAGE_GOOGLE_EDIT_HELP"] = "Для начала использования необходимо активировать <a href=\"https://cloud.google.com/storage/docs/signup\">Google Storage for Developers</a>. Далее в <a href=\"https://code.google.com/apis/console#:storage\">консоли управления API Google</a> необходимо активировать совместимый доступ (Legacy Access) и включить биллинг."; ?>lang/ru/classes/general/storage_service_selectel.php000064400000000371150241560060016742 0ustar00<? $MESS["CLO_STORAGE_SELECTEL_EDIT_USER"] = "Имя пользователя (API user)"; $MESS["CLO_STORAGE_SELECTEL_EDIT_KEY"] = "Ключ доступа (API key)"; $MESS["CLO_STORAGE_SELECTEL_EDIT_HOST"] = "Имя сервера (API host)"; ?>lang/ru/classes/general/storage.php000064400000001013150241560060013334 0ustar00<? $MESS["CLO_STORAGE_MENU"] = "Облачные хранилища"; $MESS["CLO_STORAGE_TITLE"] = "Просмотр и управление файлами в облачных хранилищах"; $MESS["CLO_STORAGE_UPLOAD_MENU"] = "Переместить в облако"; $MESS["CLO_STORAGE_UPLOAD_CONF"] = "Вы уверены, что хотите выгрузить файл в облачное хранилище?"; $MESS["CLO_404_ON_MOVED_FILE"] = "404 ошибка после перемещения файла"; ?>lang/ru/classes/general/security_service_s3.php000064400000000312150241560060015665 0ustar00<? $MESS["CLO_SECSERV_S3_XML_PARSE_ERROR"] = "нераспознанный ответ службы (ошибка ##errno#)"; $MESS["CLO_SECSERV_S3_XML_ERROR"] = "ошибка службы: #errmsg#"; ?>lang/ru/classes/general/storage_bucket.php000064400000004321150241560060014676 0ustar00<? $MESS["CLO_STORAGE_WRONG_SERVICE"] = "Задана неверная служба контейнера."; $MESS["CLO_STORAGE_EMPTY_BUCKET"] = "Не задан идентификатор контейнера."; $MESS["CLO_STORAGE_BAD_BUCKET_NAME"] = "Идентификатор контейнера содержит недопустимые символы (разрешены символы латиницы в нижнем регистре, цифры и знак: \"-\")."; $MESS["CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH"] = "Длина идентификатора контейнера должна быть не менее 2-х символов и не более 64-х."; $MESS["CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH2"] = "Длина компонента идентификатора контейнера (подстрока между точками) должна быть не менее 2-х символов и не более 64-х."; $MESS["CLO_STORAGE_BAD_BUCKET_NAME2"] = "Идентификатор контейнера должен начинаться и заканчиваться на букву или цифру."; $MESS["CLO_STORAGE_BAD_BUCKET_NAME3"] = "Рядом с символом точки могут быть только буквы или цифры."; $MESS["CLO_STORAGE_BUCKET_ALREADY_EXISTS"] = "Контейнер с таким идентификатором уже существует в облачном хранилище. Уникальность имени проверяется по всем пользователям облачного хранилища."; $MESS["CLO_STORAGE_DB_DELETE_ERROR"] = "Контейнер в облаке удален, но произошла ошибка удаления описания контейнера из базы данных."; $MESS["CLO_STORAGE_CLOUD_DELETE_ERROR"] = "Ошибка удаления контейнера: #error_msg#."; $MESS["CLO_STORAGE_CLOUD_BUCKET_NOT_EMPTY"] = "Ошибка удаления контейнера: в контейнере есть файлы."; $MESS["CLO_STORAGE_UNKNOWN_SERVICE"] = "неизвестная служба"; $MESS["CLO_STORAGE_CLOUD_ADD_ERROR"] = "Ошибка добавления контейнера: #error_msg#."; ?>lang/ru/admin/task_description.php000064400000001424150241560060013261 0ustar00<? $MESS["TASK_NAME_CLOUDS_DENIED"]="Доступ закрыт"; $MESS["TASK_NAME_CLOUDS_BROWSE"]="Выбор файлов"; $MESS["TASK_NAME_CLOUDS_UPLOAD"]="Перемещение файлов"; $MESS["TASK_NAME_CLOUDS_FULL_ACCESS"]="Полный административный доступ"; $MESS["TASK_DESC_CLOUDS_DENIED"]="Доступ к модулю запрещен"; $MESS["TASK_DESC_CLOUDS_BROWSE"]="Просмотр содержимого облачных хранилищ"; $MESS["TASK_DESC_CLOUDS_UPLOAD"]="Перемещение файлов в облачные хранилища из структуры сайта и выгрузка новых"; $MESS["TASK_DESC_CLOUDS_FULL_ACCESS"]="Разрешен полный доступ, включая настройки."; ?>lang/ru/admin/menu.php000064400000000241150241560060010654 0ustar00<? $MESS["CLO_MENU_ITEM"] = "Облачные хранилища"; $MESS["CLO_MENU_TITLE"] = "Управление облачными хранилищами"; ?>lang/ru/admin/clouds_storage_list.php000064400000005661150241560060013773 0ustar00<? $MESS["CLO_STORAGE_LIST_ADD"] = "Добавить"; $MESS["CLO_STORAGE_LIST_ADD_TITLE"] = "Добавить новое подключение к облачному хранилищу"; $MESS["CLO_STORAGE_LIST_ID"] = "ID"; $MESS["CLO_STORAGE_LIST_ACTIVE"] = "Активность"; $MESS["CLO_STORAGE_LIST_MODE"] = "Режим"; $MESS["CLO_STORAGE_LIST_READ_ONLY"] = "Чтение"; $MESS["CLO_STORAGE_LIST_READ_WRITE"] = "Чтение/Запись"; $MESS["CLO_STORAGE_LIST_SORT"] = "Сортировка"; $MESS["CLO_STORAGE_LIST_SERVICE"] = "Сервис"; $MESS["CLO_STORAGE_LIST_BUCKET"] = "Контейнер"; $MESS["CLO_STORAGE_LIST_FILE_COUNT"] = "Файлов"; $MESS["CLO_STORAGE_LIST_FILE_SIZE"] = "Объем"; $MESS["CLO_STORAGE_LIST_EDIT"] = "Изменить"; $MESS["CLO_STORAGE_LIST_MOVE_FILE_ERROR"] = "Ошибка перемещения файла в облачное хранилище"; $MESS["CLO_STORAGE_LIST_START_MOVE_FILES"] = "Переместить файлы в облачное хранилище"; $MESS["CLO_STORAGE_LIST_CONT_MOVE_FILES"] = "Продолжить перемещение файлов в облачное хранилище"; $MESS["CLO_STORAGE_LIST_MOVE_LOCAL"] = "Вернуть файлы из облачного хранилища"; $MESS["CLO_STORAGE_LIST_MOVE_LOCAL_CONF"] = "Вы уверены, что хотите вернуть файлы из облачного хранилища на диски сервера?"; $MESS["CLO_STORAGE_LIST_DEACTIVATE"] = "Деактивировать"; $MESS["CLO_STORAGE_LIST_DEACTIVATE_CONF"] = "Деактивировать подключение к облачному хранилищу?"; $MESS["CLO_STORAGE_LIST_ACTIVATE"] = "Активировать"; $MESS["CLO_STORAGE_LIST_DELETE"] = "Удалить"; $MESS["CLO_STORAGE_LIST_DELETE_CONF"] = "Удалить подключение к облачному хранилищу?"; $MESS["CLO_STORAGE_LIST_CANNOT_DELETE"] = "Ошибка удаления: #error_msg#."; $MESS["CLO_STORAGE_LIST_TITLE"] = "Облачные хранилища"; $MESS["CLO_STORAGE_LIST_MOVE_IN_PROGRESS"] = "Идет перенос файлов в облачное хранилище."; $MESS["CLO_STORAGE_LIST_MOVE_DONE"] = "Перенос файлов в облачное хранилище завершен."; $MESS["CLO_STORAGE_LIST_MOVE_PROGRESS"] = " Всего обработано <b>#total#</b> файлов.<br> Из них перемещено <b>#moved# (#bytes#)</b> и пропущено <b>#skiped#</b>. "; $MESS["CLO_STORAGE_LIST_STOP"] = "Остановить"; $MESS["CLO_STORAGE_LIST_DOWNLOAD_IN_PROGRESS"] = "Идет выгрузка файлов из облачного хранилища."; $MESS["CLO_STORAGE_LIST_DOWNLOAD_PROGRESS"] = " Осталось выгрузить <b>#remain# (#bytes#)</b>. "; $MESS["CLO_STORAGE_LIST_DOWNLOAD_DONE"] = "Возврат файлов из облачного хранилища завершен."; ?>lang/ru/admin/clouds_file_list.php000064400000003400150241560060013233 0ustar00<? $MESS["CLO_STORAGE_FILE_NAME"] = "Название"; $MESS["CLO_STORAGE_FILE_SIZE"] = "Размер"; $MESS["CLO_STORAGE_FILE_DELETE"] = "Удалить"; $MESS["CLO_STORAGE_FILE_DELETE_CONF"] = "Удалить файл без возможности восстановления?"; $MESS["CLO_STORAGE_FILE_SHOW_DIR_SIZE"] = "Размеры каталогов"; $MESS["CLO_STORAGE_FILE_SHOW_DIR_SIZE_TITLE"] = "Показать размеры каталогов с учетом вложенности"; $MESS["CLO_STORAGE_FILE_LIST_ERROR"] = "Ошибка получения списка файлов"; $MESS["CLO_STORAGE_FILE_UPLOAD_ERROR"] = "Ошибка выгрузки файла:"; $MESS["CLO_STORAGE_FILE_EXISTS_ERROR"] = "Файл с таким именем уже загружен в облачное хранилище."; $MESS["CLO_STORAGE_FILE_OPEN_ERROR"] = "Ошибка открытия файла для чтения."; $MESS["CLO_STORAGE_FILE_UNKNOWN_ERROR"] = "Неизвестная ошибка с кодом [#CODE#]."; $MESS["CLO_STORAGE_FILE_UPLOAD_IN_PROGRESS"] = "Идет выгрузка файла:"; $MESS["CLO_STORAGE_FILE_UPLOAD_DONE"] = "Выгрузка файла завершена:"; $MESS["CLO_STORAGE_FILE_UPLOAD_PROGRESS"] = " Выгружено: <b>#bytes#</b> из <b>#file_size#</b>. "; $MESS["CLO_STORAGE_FILE_STOP"] = "Остановить"; $MESS["CLO_STORAGE_FILE_UPLOAD"] = "Новый файл"; $MESS["CLO_STORAGE_FILE_UPLOAD_TITLE"] = "Выгрузить новый файл в облачное хранилище."; $MESS["CLO_STORAGE_FILE_UPLOAD_BTN"] = "Выгрузить"; $MESS["CLO_STORAGE_FILE_CANCEL_BTN"] = "Отмена"; $MESS["CLO_STORAGE_FILE_UPLOAD_INPUT"] = "Файл"; $MESS["CLO_STORAGE_FILE_PATH_INPUT"] = "Путь"; ?>lang/ru/admin/clouds_storage_edit.php000064400000006161150241560060013741 0ustar00<? $MESS["CLO_STORAGE_EDIT_TAB"] = "Подключение"; $MESS["CLO_STORAGE_EDIT_TAB_TITLE"] = "Настройка параметров подключения и использования облачного хранилища"; $MESS["CLO_STORAGE_EDIT_TAB2"] = "Правила"; $MESS["CLO_STORAGE_EDIT_TAB2_TITLE"] = "Настройка правил для отбора файлов в облачное хранилище"; $MESS["CLO_STORAGE_EDIT_EDIT_TITLE"] = "Редактирование подключения к облачному хранилищу"; $MESS["CLO_STORAGE_EDIT_ADD_TITLE"] = "Новое подключение к облачному хранилищу"; $MESS["CLO_STORAGE_EDIT_MENU_LIST"] = "Список"; $MESS["CLO_STORAGE_EDIT_MENU_LIST_TITLE"] = "Список подключений к облачным хранилищам"; $MESS["CLO_STORAGE_EDIT_ID"] = "ID"; $MESS["CLO_STORAGE_EDIT_ACTIVE"] = "Активность"; $MESS["CLO_STORAGE_EDIT_SORT"] = "Сортировка"; $MESS["CLO_STORAGE_EDIT_SERVICE_ID"] = "Провайдер"; $MESS["CLO_STORAGE_EDIT_LOCATION"] = "Регион"; $MESS["CLO_STORAGE_EDIT_BUCKET"] = "Контейнер"; $MESS["CLO_STORAGE_EDIT_READ_ONLY"] = "Только для чтения"; $MESS["CLO_STORAGE_EDIT_CNAME"] = "Каноническое имя домена (<a href=\"http://en.wikipedia.org/wiki/CNAME_record\">CNAME</a>)"; $MESS["CLO_STORAGE_EDIT_MODULE"] = "Список модулей"; $MESS["CLO_STORAGE_EDIT_EXTENSIONS"] = "Список расширений"; $MESS["CLO_STORAGE_EDIT_SIZE"] = "Список размеров"; $MESS["CLO_STORAGE_EDIT_ADD_FILE_RULE"] = "Добавить новое правило"; $MESS["CLO_STORAGE_EDIT_SAVE_ERROR"] = "Ошибка сохранения подключения к облачному хранилищу"; $MESS["CLO_STORAGE_EDIT_RULES_NOTE"] = "Для того чтобы правило сработало, файл должен удовлетворять всем трем условиям хотя бы одного правила."; $MESS["CLO_STORAGE_EDIT_RULES_NOTE1"] = "Список идентификаторов модулей. Например: iblock, advertising. Если не задан, то под действие правила подпадают файлы любых модулей."; $MESS["CLO_STORAGE_EDIT_RULES_NOTE2"] = "Список расширений файлов для хранения в облачном хранилище. Например: gif, png, jpeg, jpg. Если не задан, то под действие правила подпадают файлы с любым расширением. Список является нечувствительным к регистру."; $MESS["CLO_STORAGE_EDIT_RULES_NOTE3"] = "Список размеров файлов. Допустимо использовать суффиксы, такие как: K, M или G. Так же возможно задавать диапазоны размеров. Например: 1K-1M, 2.3M-. Если не задан, то под действие правила подпадают файлы любого размера."; ?>lang/ru/admin/operation_description.php000064400000000544150241560060014321 0ustar00<? $MESS["OP_NAME_CLOUDS_BROWSE"] = "Просмотр содержимого облачных хранилищ"; $MESS["OP_NAME_CLOUDS_UPLOAD"] = "Загрузка новых файлов и выгрузка существующих"; $MESS["OP_NAME_CLOUDS_CONFIG"] = "Настройка подключений к облачным хранилищам"; ?>lang/ru/admin/clouds_file_search.php000064400000001034150241560060013526 0ustar00<? $MESS["CLO_STORAGE_SEARCH_TITLE"] = "Выбор файла из облачного хранилища"; $MESS["CLO_STORAGE_SEARCH_BUCKET"] = "Облачное хранилище"; $MESS["CLO_STORAGE_SEARCH_CHOOSE_BUCKET"] = "Выберите облачное хранилище"; $MESS["CLO_STORAGE_SEARCH_PATH"] = "Путь"; $MESS["CLO_STORAGE_SEARCH_NAME"] = "Название"; $MESS["CLO_STORAGE_SEARCH_SIZE"] = "Размер"; $MESS["CLO_STORAGE_SEARCH_LIST_ERROR"] = "Ошибка получения списка файлов"; ?>lang/ru/options.php000064400000000257150241560060010322 0ustar00<? $MESS["CLO_OPTIONS_LOG_404_ERRORS"] = "Записывать 404 ошибки на перемещенных в облака файлах в журнал событий:"; ?>lang/en/install/index.php000064400000000377150241560060011363 0ustar00<? $MESS["CLO_MODULE_NAME"] = "Cloud Storages"; $MESS["CLO_MODULE_DESCRIPTION"] = "Supports cloud file storages."; $MESS["CLO_INSTALL_TITLE"] = "Cloud Storages Module Installation"; $MESS["CLO_UNINSTALL_TITLE"] = "Cloud Storages Module Uninstallation"; ?>lang/en/install/step1.php000064400000000103150241560060011273 0ustar00<? $MESS["CLO_INSTALL"] = "Cloud Storages module installation."; ?>lang/en/classes/general/storage_service_clodo.php000064400000000303150241560060016211 0ustar00<? $MESS["CLO_STORAGE_CLODO_EDIT_USER"] = "User name (API user)"; $MESS["CLO_STORAGE_CLODO_EDIT_KEY"] = "Access key (API key)"; $MESS["CLO_STORAGE_CLODO_EDIT_HOST"] = "Server name (API host)"; ?>lang/en/classes/general/storage_upload.php000064400000000120150241560060014652 0ustar00<? $MESS["CLO_STORAGE_UPLOAD_ERROR"] = "Error uploading file chunk: #errno#"; ?>lang/en/classes/general/storage_service_s3.php000064400000001415150241560060015443 0ustar00<? $MESS["CLO_STORAGE_S3_XML_PARSE_ERROR"] = "unrecognized service response (error ##errno#)"; $MESS["CLO_STORAGE_S3_XML_ERROR"] = "service error: #errmsg#"; $MESS["CLO_STORAGE_S3_EMPTY_ACCESS_KEY"] = "The access key is not specified."; $MESS["CLO_STORAGE_S3_EMPTY_SECRET_KEY"] = "The secret key is not specified."; $MESS["CLO_STORAGE_S3_EDIT_ACCESS_KEY"] = "Access Key"; $MESS["CLO_STORAGE_S3_EDIT_SECRET_KEY"] = "Secret Key"; $MESS["CLO_STORAGE_S3_EDIT_HELP"] = "Before you start using this service, you have to register with <a href=\"http://aws.amazon.com/s3/\">Amazon</a> and activate S3 access. The access and secret keys can be obtained at <a href=\"https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=access-key\">Security Credentials</a>."; ?>lang/en/classes/general/storage_service_openstack.php000064400000001141150241560060017101 0ustar00<? $MESS["CLO_STORAGE_OPENSTACK_EMPTY_HOST"] = "The server name is now specified."; $MESS["CLO_STORAGE_OPENSTACK_EMPTY_USER"] = "The user name is not specified."; $MESS["CLO_STORAGE_OPENSTACK_EMPTY_KEY"] = "The access key is not specified."; $MESS["CLO_STORAGE_OPENSTACK_ERROR_GET_TOKEN"] = "Authorization error. Please check the settings."; $MESS["CLO_STORAGE_OPENSTACK_EDIT_USER"] = "User name (API user)"; $MESS["CLO_STORAGE_OPENSTACK_EDIT_KEY"] = "Access key (API key)"; $MESS["CLO_STORAGE_OPENSTACK_EDIT_HOST"] = "Server name (API host)"; $MESS["CLO_STORAGE_OPENSTACK_FORCE_HTTP"] = "Always use HTTP"; ?>lang/en/classes/general/storage_service_google.php000064400000001637150241560060016400 0ustar00<? $MESS["CLO_STORAGE_GOOGLE_XML_PARSE_ERROR"] = "unrecognized service response (error ##errno#)"; $MESS["CLO_STORAGE_GOOGLE_XML_ERROR"] = "service error: #errmsg#"; $MESS["CLO_STORAGE_GOOGLE_EMPTY_ACCESS_KEY"] = "The access key is not specified."; $MESS["CLO_STORAGE_GOOGLE_EMPTY_SECRET_KEY"] = "The secret key is not specified."; $MESS["CLO_STORAGE_GOOGLE_EMPTY_PROJECT_ID"] = "The project ID is not specified."; $MESS["CLO_STORAGE_GOOGLE_EDIT_PROJECT_ID"] = "Project ID"; $MESS["CLO_STORAGE_GOOGLE_EDIT_ACCESS_KEY"] = "Access Key"; $MESS["CLO_STORAGE_GOOGLE_EDIT_SECRET_KEY"] = "Secret Key"; $MESS["CLO_STORAGE_GOOGLE_EDIT_HELP"] = "Before you start using this service, you have to activate <a href=\"https://cloud.google.com/storage/docs/signup\">Google Storage for Developers</a>. Then, use <a href=\"https://code.google.com/apis/console#:storage\">API Google console</a> to activate Legacy Access and enable billing."; ?>lang/en/classes/general/storage_service_selectel.php000064400000000314150241560060016713 0ustar00<? $MESS["CLO_STORAGE_SELECTEL_EDIT_USER"] = "User name (API user)"; $MESS["CLO_STORAGE_SELECTEL_EDIT_KEY"] = "Access key (API key)"; $MESS["CLO_STORAGE_SELECTEL_EDIT_HOST"] = "Server name (API host)"; ?>lang/en/classes/general/storage.php000064400000000545150241560060013321 0ustar00<? $MESS["CLO_STORAGE_MENU"] = "Cloud Storage"; $MESS["CLO_STORAGE_TITLE"] = "View and manage files in cloud storages"; $MESS["CLO_STORAGE_UPLOAD_MENU"] = "Move to cloud storage"; $MESS["CLO_STORAGE_UPLOAD_CONF"] = "Are you sure you want to upload the file to cloud storage?"; $MESS["CLO_404_ON_MOVED_FILE"] = "Error 404 occurred while moving the file."; ?>lang/en/classes/general/security_service_s3.php000064400000000240150241560060015641 0ustar00<? $MESS["CLO_SECSERV_S3_XML_PARSE_ERROR"] = "unrecognized service response (error ##errno#)"; $MESS["CLO_SECSERV_S3_XML_ERROR"] = "service error: #errmsg#"; ?>lang/en/classes/general/storage_bucket.php000064400000002604150241560060014654 0ustar00<? $MESS["CLO_STORAGE_WRONG_SERVICE"] = "Wrong bucket service."; $MESS["CLO_STORAGE_EMPTY_BUCKET"] = "The bucket ID is missing."; $MESS["CLO_STORAGE_BAD_BUCKET_NAME"] = "The bucket ID contains invalid characters (use only lowercase Latin letters, digits and dashes \"-\")."; $MESS["CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH"] = "A valid bucket ID must contain from 2 to 64 characters."; $MESS["CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH2"] = "The length of each part of the bucket ID (strings between dots) must contain from 2 to 64 characters. "; $MESS["CLO_STORAGE_BAD_BUCKET_NAME2"] = "The bucket ID must begin and end with a letter or a digit."; $MESS["CLO_STORAGE_BAD_BUCKET_NAME3"] = "Only digit and letter symbols are permitted to be next to a dot (before and after). "; $MESS["CLO_STORAGE_BUCKET_ALREADY_EXISTS"] = "A bucket with this ID already exists in the cloud storage. The ID must be unique across all the cloud storage users."; $MESS["CLO_STORAGE_DB_DELETE_ERROR"] = "The cloud bucket has been deleted, but the bucket description has failed to be deleted from the database."; $MESS["CLO_STORAGE_CLOUD_DELETE_ERROR"] = "Error deleting the bucket: #error_msg#."; $MESS["CLO_STORAGE_CLOUD_BUCKET_NOT_EMPTY"] = "Error deleting the bucket: the container still has files."; $MESS["CLO_STORAGE_UNKNOWN_SERVICE"] = "unknown service"; $MESS["CLO_STORAGE_CLOUD_ADD_ERROR"] = "Error creating a bucket: #error_msg#."; ?>lang/en/admin/task_description.php000064400000000770150241560060013240 0ustar00<? $MESS["TASK_NAME_CLOUDS_DENIED"] = "Access denied"; $MESS["TASK_NAME_CLOUDS_BROWSE"] = "Select files"; $MESS["TASK_NAME_CLOUDS_UPLOAD"] = "Move files"; $MESS["TASK_NAME_CLOUDS_FULL_ACCESS"] = "Full access"; $MESS["TASK_DESC_CLOUDS_DENIED"] = "Access denied"; $MESS["TASK_DESC_CLOUDS_BROWSE"] = "Browse cloud storages"; $MESS["TASK_DESC_CLOUDS_UPLOAD"] = "Upload new files from Site Explorer and download existing files"; $MESS["TASK_DESC_CLOUDS_FULL_ACCESS"] = "Full access to files and settings."; ?>lang/en/admin/menu.php000064400000000143150241560060010631 0ustar00<? $MESS["CLO_MENU_ITEM"] = "Cloud Storages"; $MESS["CLO_MENU_TITLE"] = "Manage Cloud Storages"; ?>lang/en/admin/clouds_storage_list.php000064400000004155150241560060013744 0ustar00<? $MESS["CLO_STORAGE_LIST_ADD"] = "Add"; $MESS["CLO_STORAGE_LIST_ADD_TITLE"] = "Adds a new cloud storage connection"; $MESS["CLO_STORAGE_LIST_ID"] = "ID"; $MESS["CLO_STORAGE_LIST_ACTIVE"] = "Active"; $MESS["CLO_STORAGE_LIST_MODE"] = "Mode"; $MESS["CLO_STORAGE_LIST_READ_ONLY"] = "Read-only"; $MESS["CLO_STORAGE_LIST_READ_WRITE"] = "Read/Write"; $MESS["CLO_STORAGE_LIST_SORT"] = "Sorting"; $MESS["CLO_STORAGE_LIST_SERVICE"] = "Service"; $MESS["CLO_STORAGE_LIST_BUCKET"] = "Bucket"; $MESS["CLO_STORAGE_LIST_FILE_COUNT"] = "Files"; $MESS["CLO_STORAGE_LIST_FILE_SIZE"] = "Size"; $MESS["CLO_STORAGE_LIST_EDIT"] = "Edit"; $MESS["CLO_STORAGE_LIST_START_MOVE_FILES"] = "Upload files to cloud storage"; $MESS["CLO_STORAGE_LIST_CONT_MOVE_FILES"] = "Continue moving files to cloud storage"; $MESS["CLO_STORAGE_LIST_MOVE_LOCAL"] = "Download files from cloud storage"; $MESS["CLO_STORAGE_LIST_MOVE_LOCAL_CONF"] = "Are you sure you want to move the files from the cloud back to the server?"; $MESS["CLO_STORAGE_LIST_DEACTIVATE"] = "Deactivate"; $MESS["CLO_STORAGE_LIST_DEACTIVATE_CONF"] = "Deactivate cloud storage connection?"; $MESS["CLO_STORAGE_LIST_ACTIVATE"] = "Activate"; $MESS["CLO_STORAGE_LIST_DELETE"] = "Delete"; $MESS["CLO_STORAGE_LIST_DELETE_CONF"] = "Delete cloud storage connection?"; $MESS["CLO_STORAGE_LIST_CANNOT_DELETE"] = "Cannot delete connection: #error_msg#."; $MESS["CLO_STORAGE_LIST_TITLE"] = "Cloud Storages"; $MESS["CLO_STORAGE_LIST_MOVE_IN_PROGRESS"] = "Files are now being moved to the storage."; $MESS["CLO_STORAGE_LIST_MOVE_DONE"] = "Files has been moved to the storage."; $MESS["CLO_STORAGE_LIST_MOVE_PROGRESS"] = " Total files processed: <b>#total#</b>.<br> Moved files: <b>#moved# (#bytes#)</b>, skipped files: <b>#skiped#</b>. "; $MESS["CLO_STORAGE_LIST_STOP"] = "Stop"; $MESS["CLO_STORAGE_LIST_DOWNLOAD_IN_PROGRESS"] = "Files are now being downloaded from the storage."; $MESS["CLO_STORAGE_LIST_DOWNLOAD_PROGRESS"] = " <b>#remain# (#bytes#)</b> remains. "; $MESS["CLO_STORAGE_LIST_DOWNLOAD_DONE"] = "Files has been downloaded from the storage."; $MESS["CLO_STORAGE_LIST_MOVE_FILE_ERROR"] = "Error moving the file to cloud storage."; ?>lang/en/admin/clouds_file_list.php000064400000002470150241560060013215 0ustar00<? $MESS["CLO_STORAGE_FILE_NAME"] = "Name"; $MESS["CLO_STORAGE_FILE_SIZE"] = "Size"; $MESS["CLO_STORAGE_FILE_DELETE"] = "Delete"; $MESS["CLO_STORAGE_FILE_DELETE_CONF"] = "Do you want to delete the file irreversibly?"; $MESS["CLO_STORAGE_FILE_SHOW_DIR_SIZE"] = "Folder size"; $MESS["CLO_STORAGE_FILE_SHOW_DIR_SIZE_TITLE"] = "Show folder size, including nested folders"; $MESS["CLO_STORAGE_FILE_LIST_ERROR"] = "Error getting file list."; $MESS["CLO_STORAGE_FILE_UPLOAD_ERROR"] = "File upload error:"; $MESS["CLO_STORAGE_FILE_EXISTS_ERROR"] = "A file with this name already exists in the cloud storage."; $MESS["CLO_STORAGE_FILE_OPEN_ERROR"] = "Error opening the file for reading."; $MESS["CLO_STORAGE_FILE_UNKNOWN_ERROR"] = "Unknown error [#CODE#]."; $MESS["CLO_STORAGE_FILE_UPLOAD_IN_PROGRESS"] = "Now uploading file:"; $MESS["CLO_STORAGE_FILE_UPLOAD_DONE"] = "File uploaded:"; $MESS["CLO_STORAGE_FILE_UPLOAD_PROGRESS"] = " Uploaded: <b>#bytes#</b> of <b>#file_size#</b>. "; $MESS["CLO_STORAGE_FILE_STOP"] = "Stop"; $MESS["CLO_STORAGE_FILE_UPLOAD"] = "New file"; $MESS["CLO_STORAGE_FILE_UPLOAD_TITLE"] = "Upload new file to cloud storage."; $MESS["CLO_STORAGE_FILE_UPLOAD_BTN"] = "Upload"; $MESS["CLO_STORAGE_FILE_CANCEL_BTN"] = "Cancel"; $MESS["CLO_STORAGE_FILE_UPLOAD_INPUT"] = "File"; $MESS["CLO_STORAGE_FILE_PATH_INPUT"] = "Path"; ?>lang/en/admin/clouds_storage_edit.php000064400000003776150241560060013726 0ustar00<? $MESS["CLO_STORAGE_EDIT_TAB"] = "Connection"; $MESS["CLO_STORAGE_EDIT_TAB_TITLE"] = "Configure cloud storage connection parameters"; $MESS["CLO_STORAGE_EDIT_TAB2"] = "Rules"; $MESS["CLO_STORAGE_EDIT_TAB2_TITLE"] = "Set file selection rules for the cloud storage"; $MESS["CLO_STORAGE_EDIT_EDIT_TITLE"] = "Changes cloud storage connection parameters"; $MESS["CLO_STORAGE_EDIT_ADD_TITLE"] = "Adds a new cloud storage connection"; $MESS["CLO_STORAGE_EDIT_MENU_LIST"] = "Connections"; $MESS["CLO_STORAGE_EDIT_MENU_LIST_TITLE"] = "Shows available cloud storage connections"; $MESS["CLO_STORAGE_EDIT_ID"] = "ID"; $MESS["CLO_STORAGE_EDIT_ACTIVE"] = "Active"; $MESS["CLO_STORAGE_EDIT_SORT"] = "Sorting"; $MESS["CLO_STORAGE_EDIT_SERVICE_ID"] = "Provider"; $MESS["CLO_STORAGE_EDIT_LOCATION"] = "Location"; $MESS["CLO_STORAGE_EDIT_BUCKET"] = "Bucket"; $MESS["CLO_STORAGE_EDIT_READ_ONLY"] = "Read-only"; $MESS["CLO_STORAGE_EDIT_CNAME"] = "Domain canonic name (<a href=\"http://en.wikipedia.org/wiki/CNAME_record\">CNAME</a>)"; $MESS["CLO_STORAGE_EDIT_MODULE"] = "Modules"; $MESS["CLO_STORAGE_EDIT_EXTENSIONS"] = "Extensions"; $MESS["CLO_STORAGE_EDIT_SIZE"] = "Sizes"; $MESS["CLO_STORAGE_EDIT_ADD_FILE_RULE"] = "Add new rule"; $MESS["CLO_STORAGE_EDIT_SAVE_ERROR"] = "Error saving cloud storage connection"; $MESS["CLO_STORAGE_EDIT_RULES_NOTE"] = "The rule triggers only if a file satisfies all the rule conditions. If a file doesn't match at least one rule, it will not be put in the cloud."; $MESS["CLO_STORAGE_EDIT_RULES_NOTE1"] = "Module identifiers. Example: iblock, advertising. Empty module list matches all files of all modules."; $MESS["CLO_STORAGE_EDIT_RULES_NOTE2"] = "Extensions of files that can be stored in the cloud. Example: gif, png, jpeg, jpg. Empty extension list matches any file. This list is case-insensitive."; $MESS["CLO_STORAGE_EDIT_RULES_NOTE3"] = "File sizes. Use the file size suffixes to denote the file size: K, M or G. Size ranges are possible, for example: 1K-1M, 2.3M-. If this field is empty, any file size will match."; ?>lang/en/admin/operation_description.php000064400000000335150241560060014273 0ustar00<? $MESS["OP_NAME_CLOUDS_BROWSE"] = "Browse cloud storages"; $MESS["OP_NAME_CLOUDS_UPLOAD"] = "Upload new files and download existing files"; $MESS["OP_NAME_CLOUDS_CONFIG"] = "Edit cloud storage connection parameters"; ?>lang/en/admin/clouds_file_search.php000064400000000611150241560060013502 0ustar00<? $MESS["CLO_STORAGE_SEARCH_TITLE"] = "Select file in cloud storage"; $MESS["CLO_STORAGE_SEARCH_BUCKET"] = "Cloud storage"; $MESS["CLO_STORAGE_SEARCH_CHOOSE_BUCKET"] = "Select cloud storage"; $MESS["CLO_STORAGE_SEARCH_PATH"] = "Path"; $MESS["CLO_STORAGE_SEARCH_NAME"] = "Name"; $MESS["CLO_STORAGE_SEARCH_SIZE"] = "Size"; $MESS["CLO_STORAGE_SEARCH_LIST_ERROR"] = "Error getting file list."; ?>lang/en/options.php000064400000000130150241560060010264 0ustar00<? $MESS["CLO_OPTIONS_LOG_404_ERRORS"] = "Log 404 errors for files in cloud storage"; ?>default_option.php000064400000000134150241560060010266 0ustar00<? $clouds_default_option = array( "log_404_errors" => "N", "delayed_resize" => "N", ); ?>install/db/mysql/install.sql000064400000002251150241560060012132 0ustar00CREATE TABLE b_clouds_file_bucket ( ID INT(11) NOT NULL auto_increment, ACTIVE CHAR(1) DEFAULT 'Y', SORT INT(11) DEFAULT 500, READ_ONLY CHAR(1) DEFAULT 'N', SERVICE_ID VARCHAR(50), BUCKET VARCHAR(63), LOCATION VARCHAR(50), CNAME VARCHAR(100), FILE_COUNT INT(11) default 0, FILE_SIZE float default 0, LAST_FILE_ID INT(11), PREFIX VARCHAR(100), SETTINGS TEXT, FILE_RULES TEXT, PRIMARY KEY pk_b_clouds_file_bucket(ID) ); CREATE TABLE b_clouds_file_upload ( ID VARCHAR(32) NOT NULL, TIMESTAMP_X TIMESTAMP NOT NULL, FILE_PATH VARCHAR(500) NOT NULL, FILE_SIZE INT(11) NULL, TMP_FILE VARCHAR(500) NULL, BUCKET_ID INT(11) NOT NULL, PART_SIZE INT(11) NOT NULL, PART_NO INT(11) NOT NULL, PART_FAIL_COUNTER INT(11) NOT NULL, NEXT_STEP TEXT, PRIMARY KEY pk_b_clouds_file_upload(ID) ); CREATE TABLE b_clouds_file_resize ( ID INT(11) NOT NULL auto_increment, TIMESTAMP_X TIMESTAMP NOT NULL, ERROR_CODE CHAR(1) NOT NULL DEFAULT '0', FILE_ID INT(11), PARAMS TEXT, FROM_PATH VARCHAR(500), TO_PATH VARCHAR(500), PRIMARY KEY pk_b_file_resize(ID), INDEX ix_b_file_resize_ts (TIMESTAMP_X), INDEX ix_b_file_resize_path (TO_PATH(100)), INDEX ix_b_file_resize_file (FILE_ID) ); install/db/mysql/uninstall.sql000064400000000201150241560060012466 0ustar00DROP TABLE if exists b_clouds_file_upload; DROP TABLE if exists b_clouds_file_bucket; DROP TABLE if exists b_clouds_file_resize; install/admin/clouds_storage_list.php000064400000000141150241560060014056 0ustar00<? require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/admin/clouds_storage_list.php"); ?> install/admin/clouds_file_list.php000064400000000136150241560060013335 0ustar00<? require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/admin/clouds_file_list.php"); ?> install/admin/clouds_storage_edit.php000064400000000141150241560060014030 0ustar00<? require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/admin/clouds_storage_edit.php"); ?> install/admin/clouds_file_search.php000064400000000140150241560060013622 0ustar00<? require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/admin/clouds_file_search.php"); ?> install/unstep2.php000064400000000757150241560060010333 0ustar00<? if(!check_bitrix_sessid()) return; if($ex = $APPLICATION->GetException()) echo CAdminMessage::ShowMessage(Array( "TYPE" => "ERROR", "MESSAGE" => GetMessage("MOD_UNINST_ERR"), "DETAILS" => $ex->GetString(), "HTML" => true, )); else echo CAdminMessage::ShowNote(GetMessage("MOD_UNINST_OK")); ?> <form action="<?echo $APPLICATION->GetCurPage()?>"> <input type="hidden" name="lang" value="<?echo LANG?>"> <input type="submit" name="" value="<?echo GetMessage("MOD_BACK")?>"> <form> install/themes/.default/clouds.css000064400000000171150241560060013202 0ustar00.clouds-directory-icon { background-position: center -118px; } .clouds-up-icon { background-position: center -1574px; }install/step2.php000064400000001013150241560060007752 0ustar00<? if(!check_bitrix_sessid()) return; IncludeModuleLangFile(__FILE__); if($ex = $APPLICATION->GetException()) echo CAdminMessage::ShowMessage(Array( "TYPE" => "ERROR", "MESSAGE" => GetMessage("MOD_INST_ERR"), "DETAILS" => $ex->GetString(), "HTML" => true, )); else echo CAdminMessage::ShowNote(GetMessage("MOD_INST_OK")); ?> <form action="<?echo $APPLICATION->GetCurPage()?>"> <input type="hidden" name="lang" value="<?echo LANG?>"> <input type="submit" name="" value="<?echo GetMessage("MOD_BACK")?>"> <form>install/unstep1.php000064400000001210150241560060010313 0ustar00<form action="<?echo $APPLICATION->GetCurPage()?>"> <?=bitrix_sessid_post()?> <input type="hidden" name="lang" value="<?=LANGUAGE_ID?>"> <input type="hidden" name="id" value="clouds"> <input type="hidden" name="uninstall" value="Y"> <input type="hidden" name="step" value="2"> <?echo CAdminMessage::ShowMessage(GetMessage("MOD_UNINST_WARN"))?> <p><?echo GetMessage("MOD_UNINST_SAVE")?></p> <p><input type="checkbox" name="save_tables" id="save_tables" value="Y" checked><label for="save_tables"><?echo GetMessage("MOD_UNINST_SAVE_TABLES")?></label></p> <input type="submit" name="inst" value="<?echo GetMessage("MOD_UNINST_DEL")?>"> </form>install/index.php000064400000021063150241560060010033 0ustar00<? IncludeModuleLangFile(__FILE__); if(class_exists("clouds")) return; Class clouds extends CModule { var $MODULE_ID = "clouds"; var $MODULE_VERSION; var $MODULE_VERSION_DATE; var $MODULE_NAME; var $MODULE_DESCRIPTION; var $MODULE_CSS; var $MODULE_GROUP_RIGHTS = "Y"; function clouds() { $arModuleVersion = array(); $path = str_replace("\\", "/", __FILE__); $path = substr($path, 0, strlen($path) - strlen("/index.php")); include($path."/version.php"); $this->MODULE_VERSION = $arModuleVersion["VERSION"]; $this->MODULE_VERSION_DATE = $arModuleVersion["VERSION_DATE"]; $this->MODULE_NAME = GetMessage("CLO_MODULE_NAME"); $this->MODULE_DESCRIPTION = GetMessage("CLO_MODULE_DESCRIPTION"); } function GetModuleTasks() { return array( 'clouds_denied' => array( "LETTER" => "D", "BINDING" => "module", "OPERATIONS" => array( ), ), 'clouds_browse' => array( "LETTER" => "F", "BINDING" => "module", "OPERATIONS" => array( 'clouds_browse', ), ), 'clouds_upload' => array( "LETTER" => "U", "BINDING" => "module", "OPERATIONS" => array( 'clouds_browse', 'clouds_upload', ), ), 'clouds_full_access' => array( "LETTER" => "W", "BINDING" => "module", "OPERATIONS" => array( 'clouds_browse', 'clouds_upload', 'clouds_config', ), ), ); } function InstallDB($arParams = array()) { global $DB, $DBType, $APPLICATION; $this->errors = false; // Database tables creation if(!$DB->Query("SELECT 'x' FROM b_clouds_file_bucket WHERE 1=0", true)) { $this->errors = $DB->RunSQLBatch($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/db/".strtolower($DB->type)."/install.sql"); } if($this->errors !== false) { $APPLICATION->ThrowException(implode("<br>", $this->errors)); return false; } else { $this->InstallTasks(); RegisterModule("clouds"); CModule::IncludeModule("clouds"); RegisterModuleDependences("main", "OnEventLogGetAuditTypes", "clouds", "CCloudStorage", "GetAuditTypes"); RegisterModuleDependences("main", "OnBeforeProlog", "clouds", "CCloudStorage", "OnBeforeProlog"); RegisterModuleDependences("main", "OnAdminListDisplay", "clouds", "CCloudStorage", "OnAdminListDisplay"); RegisterModuleDependences("main", "OnBuildGlobalMenu", "clouds", "CCloudStorage", "OnBuildGlobalMenu"); RegisterModuleDependences("main", "OnFileSave", "clouds", "CCloudStorage", "OnFileSave"); RegisterModuleDependences("main", "OnGetFileSRC", "clouds", "CCloudStorage", "OnGetFileSRC"); RegisterModuleDependences("main", "OnFileCopy", "clouds", "CCloudStorage", "OnFileCopy"); RegisterModuleDependences("main", "OnFileDelete", "clouds", "CCloudStorage", "OnFileDelete"); RegisterModuleDependences("main", "OnMakeFileArray", "clouds", "CCloudStorage", "OnMakeFileArray"); RegisterModuleDependences("main", "OnBeforeResizeImage", "clouds", "CCloudStorage", "OnBeforeResizeImage"); RegisterModuleDependences("main", "OnAfterResizeImage", "clouds", "CCloudStorage", "OnAfterResizeImage"); RegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_AmazonS3", "GetObjectInstance"); RegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_GoogleStorage", "GetObjectInstance"); RegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_OpenStackStorage", "GetObjectInstance"); RegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_RackSpaceCloudFiles", "GetObjectInstance"); RegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_ClodoRU", "GetObjectInstance"); RegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_Selectel", "GetObjectInstance"); RegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_HotBox", "GetObjectInstance"); return true; } } function UnInstallDB($arParams = array()) { global $DB, $DBType, $APPLICATION; $this->errors = false; if(!array_key_exists("save_tables", $arParams) || $arParams["save_tables"] != "Y") { $this->errors = $DB->RunSQLBatch($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/db/".strtolower($DB->type)."/uninstall.sql"); $this->UnInstallTasks(); } UnRegisterModuleDependences("main", "OnEventLogGetAuditTypes", "clouds", "CCloudStorage", "GetAuditTypes"); UnRegisterModuleDependences("main", "OnBeforeProlog", "clouds", "CCloudStorage", "OnBeforeProlog"); UnRegisterModuleDependences("main", "OnAdminListDisplay", "clouds", "CCloudStorage", "OnAdminListDisplay"); UnRegisterModuleDependences("main", "OnBuildGlobalMenu", "clouds", "CCloudStorage", "OnBuildGlobalMenu"); UnRegisterModuleDependences("main", "OnFileSave", "clouds", "CCloudStorage", "OnFileSave"); UnRegisterModuleDependences("main", "OnGetFileSRC", "clouds", "CCloudStorage", "OnGetFileSRC"); UnRegisterModuleDependences("main", "OnFileCopy", "clouds", "CCloudStorage", "OnFileCopy"); UnRegisterModuleDependences("main", "OnFileDelete", "clouds", "CCloudStorage", "OnFileDelete"); UnRegisterModuleDependences("main", "OnMakeFileArray", "clouds", "CCloudStorage", "OnMakeFileArray"); UnRegisterModuleDependences("main", "OnBeforeResizeImage", "clouds", "CCloudStorage", "OnBeforeResizeImage"); UnRegisterModuleDependences("main", "OnAfterResizeImage", "clouds", "CCloudStorage", "OnAfterResizeImage"); UnRegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_AmazonS3", "GetObjectInstance"); UnRegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_GoogleStorage", "GetObjectInstance"); UnRegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_OpenStackStorage", "GetObjectInstance"); UnRegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_RackSpaceCloudFiles", "GetObjectInstance"); UnRegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_ClodoRU", "GetObjectInstance"); UnRegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_Selectel", "GetObjectInstance"); UnRegisterModuleDependences("clouds", "OnGetStorageService", "clouds", "CCloudStorageService_HotBox", "GetObjectInstance"); UnRegisterModule("clouds"); if(!defined("BX_CLOUDS_UNINSTALLED")) define("BX_CLOUDS_UNINSTALLED", true); if($this->errors !== false) { $APPLICATION->ThrowException(implode("<br>", $this->errors)); return false; } return true; } function InstallEvents() { return true; } function UnInstallEvents() { return true; } function InstallFiles($arParams = array()) { if($_ENV["COMPUTERNAME"]!='BX') { CopyDirFiles($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/admin", $_SERVER["DOCUMENT_ROOT"]."/bitrix/admin"); CopyDirFiles($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/themes", $_SERVER["DOCUMENT_ROOT"]."/bitrix/themes", true, true); } return true; } function UnInstallFiles() { if($_ENV["COMPUTERNAME"]!='BX') { DeleteDirFiles($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/admin/", $_SERVER["DOCUMENT_ROOT"]."/bitrix/admin"); DeleteDirFiles($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/themes/.default/", $_SERVER["DOCUMENT_ROOT"]."/bitrix/themes/.default"); } return true; } function DoInstall() { global $DB, $APPLICATION, $step, $USER; if($USER->IsAdmin()) { $step = IntVal($step); if($step < 2) { $APPLICATION->IncludeAdminFile(GetMessage("CLO_INSTALL_TITLE"), $_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/step1.php"); } elseif($step==2) { if($this->InstallDB()) { $this->InstallFiles(); } $GLOBALS["errors"] = $this->errors; $APPLICATION->IncludeAdminFile(GetMessage("CLO_INSTALL_TITLE"), $_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/step2.php"); } } } function DoUninstall() { global $DB, $APPLICATION, $step, $USER; if($USER->IsAdmin()) { $step = IntVal($step); if($step < 2) { $APPLICATION->IncludeAdminFile(GetMessage("CLO_UNINSTALL_TITLE"), $_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/unstep1.php"); } elseif($step == 2) { $this->UnInstallDB(array( "save_tables" => $_REQUEST["save_tables"], )); $this->UnInstallFiles(); $GLOBALS["errors"] = $this->errors; $APPLICATION->IncludeAdminFile(GetMessage("CLO_UNINSTALL_TITLE"), $_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/clouds/install/unstep2.php"); } } } } ?>install/step1.php000064400000000700150241560060007753 0ustar00<?IncludeModuleLangFile(__FILE__);?> <p><?echo GetMessage("CLO_INSTALL")?></p> <form action="<?echo $APPLICATION->GetCurPage()?>" name="form1"> <?=bitrix_sessid_post()?> <input type="hidden" name="lang" value="<?echo LANG?>"> <input type="hidden" name="id" value="clouds"> <input type="hidden" name="install" value="Y"> <input type="hidden" name="step" value="2"> <input type="submit" name="inst" value="<?echo GetMessage("MOD_INSTALL")?>"> </form>install/version.php000064400000000144150241560060010406 0ustar00<? $arModuleVersion = array( "VERSION" => "17.0.2", "VERSION_DATE" => "2017-10-13 13:00:00", ); ?>classes/general/storage_service_clodo.php000064400000005012150241560060014670 0ustar00<? IncludeModuleLangFile(__FILE__); class CCloudStorageService_ClodoRU extends CCloudStorageService_OpenStackStorage { function GetObject() { return new CCloudStorageService_ClodoRU(); } function GetID() { return "clodo_storage"; } function GetName() { return "Clodo.ru"; } function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm) { if($bVarsFromForm) $arSettings = $_POST["SETTINGS"][$this->GetID()]; else $arSettings = unserialize($arBucket["SETTINGS"]); if(!is_array($arSettings)) $arSettings = array("HOST" => "api.clodo.ru", "USER" => "", "KEY" => ""); $htmlID = htmlspecialcharsbx($this->GetID()); $result = ' <tr id="SETTINGS_2_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_CLODO_EDIT_HOST").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][HOST]" id="'.$htmlID.'HOST" value="'.htmlspecialcharsbx($arSettings['HOST']).'"><input type="text" size="55" name="'.$htmlID.'INP_HOST" id="'.$htmlID.'INP_HOST" value="'.htmlspecialcharsbx($arSettings['HOST']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'HOST\').value = this.value"></td> </tr> <tr id="SETTINGS_0_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_CLODO_EDIT_USER").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][USER]" id="'.$htmlID.'USER" value="'.htmlspecialcharsbx($arSettings['USER']).'"><input type="text" size="55" name="'.$htmlID.'INP_" id="'.$htmlID.'INP_USER" value="'.htmlspecialcharsbx($arSettings['USER']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'USER\').value = this.value"></td> </tr> <tr id="SETTINGS_1_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_CLODO_EDIT_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][KEY]" id="'.$htmlID.'KEY" value="'.htmlspecialcharsbx($arSettings['KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_KEY" id="'.$htmlID.'INP_KEY" value="'.htmlspecialcharsbx($arSettings['KEY']).'" autocomplete="off" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'KEY\').value = this.value"></td> </tr> '; return $result; } } ?>classes/general/temp_file.php000064400000005723150241560060012301 0ustar00<?php class CCloudTempFile { private static $buckets = array(); protected static function GetAbsoluteRoot() { return "/tmp"; } protected static $shutdownRegistered = false; protected static function RegisterShutdown() { if (!self::$shutdownRegistered) { register_shutdown_function(array('CCloudTempFile', 'Cleanup')); self::$shutdownRegistered = true; } } public static function GetFileName($obBucket, $file_name = '') { $dir_name = self::GetAbsoluteRoot(); $file_name = rel2abs("/", "/".$file_name); $i = 0; while(true) { $i++; if($file_name == '/') $dir_add = md5(mt_rand()); elseif($i < 25) $dir_add = substr(md5(mt_rand()), 0, 3); else $dir_add = md5(mt_rand()); $temp_path = $dir_name."/".$dir_add.$file_name; if (!$obBucket->FileExists($temp_path)) { self::$buckets[] = array( "bucket" => $obBucket, "filePath" => $temp_path, ); self::RegisterShutdown(); return $temp_path; } } } public static function GetDirectoryName($obBucket, $hours_to_keep_files = 0, $subdir = "") { if($hours_to_keep_files <= 0) return self::GetFileName(''); if($subdir === "") { $dir_name = self::GetAbsoluteRoot().'/BXTEMP-'.date('Y-m-d/H/', time()+3600*$hours_to_keep_files); $i = 0; while(true) { $i++; $dir_add = md5(mt_rand()); $temp_path = $dir_name.$dir_add."/"; if (!$obBucket->FileExists($temp_path)) break; } } else //Fixed name during the session { $subdir = implode("/", (is_array($subdir) ? $subdir : array($subdir, bitrix_sessid())))."/"; while (strpos($subdir, "//") !== false) $subdir = str_replace("//", "/", $subdir); $bFound = false; for($i = $hours_to_keep_files; $i > 0; $i--) { $dir_name = self::GetAbsoluteRoot().'/BXTEMP-'.date('Y-m-d/H/', time()+3600*$i); $temp_path = $dir_name.$subdir; $list = $obBucket->ListFiles($temp_path, true); if($list['file'] || $list['dir']) { $bFound = true; break; } } if(!$bFound) { $dir_name = self::GetAbsoluteRoot().'/BXTEMP-'.date('Y-m-d/H/', time()+3600*$hours_to_keep_files); $temp_path = $dir_name.$subdir; } } self::$buckets[] = array( "bucket" => $obBucket, "filePath" => null ); self::RegisterShutdown(); return $temp_path; } //PHP shutdown cleanup public static function Cleanup() { foreach(self::$buckets as $bucket) { /* @var \CCloudStorageBucket $obBucket */ $obBucket = $bucket['bucket']; if (!is_null($bucket['filePath']) && $obBucket->FileExists($bucket['filePath'])) { $obBucket->DeleteFile($bucket['filePath']); } else { $now = date('Y-m-d/H/', time()); $dir_name = self::GetAbsoluteRoot()."/"; $list = $obBucket->ListFiles($dir_name, true); foreach ($list['file'] as $filePath) { if (preg_match("#^BXTEMP-(....-..-../../)#", $filePath, $match) && $match[1] < $now) { $obBucket->DeleteFile($dir_name.$filePath); } } } } } } classes/general/storage_service_rackspace.php000064400000011171150241560060015527 0ustar00<? class CCloudStorageService_RackSpaceCloudFiles extends CCloudStorageService_OpenStackStorage { function GetObject() { return new CCloudStorageService_RackSpaceCloudFiles(); } function GetID() { return "rackspace_storage"; } function GetName() { return "Rackspace Cloud Files"; } function _GetToken($host, $user, $key) { $result = false; $cache_id = "v0|".$host."|".$user."|".$key; $obCache = new CPHPCache; if($obCache->InitCache(3600, $cache_id, "/")) { $result = $obCache->GetVars(); } else { $obRequest = new CHTTP; $obRequest->additional_headers["X-Auth-User"] = $user; $obRequest->additional_headers["X-Auth-Key"] = $key; $obRequest->Query("GET", $host, 80, "/v1.0"); if($obRequest->status == 301 && strlen($obRequest->headers["Location"]) > 0) { if(preg_match("#^https://(.*?)(/.*)\$#", $obRequest->headers["Location"], $arNewLocation)) { $obRequest = new CHTTP; $obRequest->additional_headers["X-Auth-User"] = $user; $obRequest->additional_headers["X-Auth-Key"] = $key; @$obRequest->Query("GET", $arNewLocation[1], 443, "/v1.0", false, "ssl://"); if($obRequest->status == 204) { if(preg_match("#^https://(.*?)(/.*)\$#", $obRequest->headers["X-Storage-Url"], $arStorage)) { $result = $obRequest->headers; $result["X-Storage-Host"] = $arStorage[1]; $result["X-Storage-Port"] = 443; $result["X-Storage-Urn"] = $arStorage[2]; $result["X-Storage-Proto"] = "ssl://"; } } } } } if(is_array($result)) { if($obCache->StartDataCache()) $obCache->EndDataCache($result); } return $result; } function SendCDNRequest($settings, $verb, $bucket, $file_name='', $params='', $content=false, $additional_headers=array()) { $arToken = $this->_GetToken($settings["HOST"], $settings["USER"], $settings["KEY"]); if(!$arToken) return false; if(isset($arToken["X-CDN-Management-Url"])) { if(preg_match("#^http://(.*?)(|:\d+)(/.*)\$#", $arToken["X-CDN-Management-Url"], $arCDN)) { $Host = $arCDN[1]; $Port = $arCDN[2]? substr($arCDN[2], 1): 80; $Urn = $arCDN[3]; $Proto = ""; } elseif(preg_match("#^https://(.*?)(|:\d+)(/.*)\$#", $arToken["X-CDN-Management-Url"], $arCDN)) { $Host = $arCDN[1]; $Port = $arCDN[2]? substr($arCDN[2], 1): 443; $Urn = $arCDN[3]; $Proto = "ssl://"; } else { return false; } } else { return false; } $obRequest = new CHTTP; $obRequest->additional_headers["X-Auth-Token"] = $arToken["X-Auth-Token"]; foreach($additional_headers as $key => $value) $obRequest->additional_headers[$key] = $value; $obRequest->Query( $verb, $Host, $Port, $Urn.CCloudUtil::URLEncode("/".$bucket.$file_name.$params, "UTF-8"), $content, $Proto ); return $obRequest; } function CreateBucket($arBucket) { global $APPLICATION; $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"] ); //CDN Enable if($this->status == 201) { $obCDNRequest = $this->SendCDNRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], '', //filename '', //params false, //content array( "X-CDN-Enabled" => "True", ) ); } return ($this->status == 201)/*Created*/ || ($this->status == 202) /*Accepted*/; } function GetFileSRC($arBucket, $arFile) { global $APPLICATION; if ($arBucket["SETTINGS"]["FORCE_HTTP"] === "Y") $proto = "http"; else $proto = ($APPLICATION->IsHTTPS()? "https": "http"); if($arBucket["CNAME"]) { $host = $proto."://".$arBucket["CNAME"]; } else { $result = false; $cache_id = md5(serialize($arBucket)); $obCache = new CPHPCache; if($obCache->InitCache(3600, $cache_id, "/")) { $result = $obCache->GetVars(); } else { $obCDNRequest = $this->SendCDNRequest( $arBucket["SETTINGS"], "HEAD", $arBucket["BUCKET"] ); if(is_object($obCDNRequest)) { if($obCDNRequest->status == 204) { $result = array(); foreach($obCDNRequest->headers as $key => $value) $result[strtolower($key)] = $value; } } } if($obCache->StartDataCache()) $obCache->EndDataCache($result); if(is_array($result)) $host = $result["x-cdn-uri"]; else return "/404.php"; } if(is_array($arFile)) $URI = ltrim($arFile["SUBDIR"]."/".$arFile["FILE_NAME"], "/"); else $URI = ltrim($arFile, "/"); if($arBucket["PREFIX"]) { if(substr($URI, 0, strlen($arBucket["PREFIX"])+1) !== $arBucket["PREFIX"]."/") $URI = $arBucket["PREFIX"]."/".$URI; } return $host."/".CCloudUtil::URLEncode($URI, "UTF-8"); } } ?>classes/general/storage_upload.php000064400000015672150241560060013351 0ustar00<? /*. require_module 'standard'; require_module 'pcre'; require_module 'hash'; require_module 'bitrix_main'; require_module 'bitrix_clouds_classes_storage_service'; require_module 'bitrix_clouds_classes_storage_bucket'; .*/ IncludeModuleLangFile(__FILE__); class CCloudStorageUpload { protected /*.string.*/ $_filePath = ""; protected /*.string.*/ $_ID = ""; protected /*.CCloudStorageBucket.*/ $obBucket; protected /*.int.*/ $_max_retries = 3; protected /*.array[string]string.*/ $_cache = null; /** * @param string $filePath * @return void */ function __construct($filePath) { $this->_filePath = $filePath; $this->_ID = "1".substr(md5($filePath), 1); } /** * @return array[string]string */ public function GetArray() { global $DB; if(!isset($this->_cache)) { $rs = $DB->Query(" SELECT * FROM b_clouds_file_upload WHERE ID = '".$this->_ID."' "); $this->_cache = $rs->Fetch(); } return $this->_cache; } /** * @return bool */ public function isStarted() { return is_array($this->GetArray()); } /** * @return void */ public function Delete() { global $DB; //TODO: clean up temp files in Clodo $DB->Query("DELETE FROM b_clouds_file_upload WHERE ID = '".$this->_ID."'"); unset($this->_cache); } /** * @return void */ public function DeleteOld() { global $DB; $DB->Query("DELETE FROM b_clouds_file_upload WHERE TIMESTAMP_X < ".$DB->CharToDateFunction(ConvertTimeStamp(time()-24*60*60))); } /** * @param int $bucket_id * @param float $fileSize * @param string $ContentType * @return bool */ function Start($bucket_id, $fileSize, $ContentType = 'binary/octet-stream', $tmpFileName = false) { global $DB; if(is_object($bucket_id)) $obBucket = $bucket_id; else $obBucket = new CCloudStorageBucket(intval($bucket_id)); if(!$obBucket->Init()) return false; if(!$this->isStarted()) { $arUploadInfo = /*.(array[string]string).*/array(); $bStarted = $obBucket->GetService()->InitiateMultipartUpload( $obBucket->GetBucketArray(), $arUploadInfo, $this->_filePath, $fileSize, $ContentType ); if($bStarted) { $bAdded = $DB->Add("b_clouds_file_upload", array( "ID" => $this->_ID, "~TIMESTAMP_X" => $DB->CurrentTimeFunction(), "FILE_PATH" => $this->_filePath, "FILE_SIZE" => $fileSize, "TMP_FILE" => $tmpFileName, "BUCKET_ID" => intval($obBucket->ID), "PART_SIZE" => $obBucket->GetService()->GetMinUploadPartSize(), "PART_NO" => 0, "PART_FAIL_COUNTER" => 0, "NEXT_STEP" => serialize($arUploadInfo), ), array("NEXT_STEP")); unset($this->_cache); return $bAdded !== false; } } return false; } /** * @param string $data * @return bool */ function Next($data, $obBucket = null) { global $APPLICATION; if($this->isStarted()) { $ar = $this->GetArray(); if($obBucket == null) $obBucket = new CCloudStorageBucket(intval($ar["BUCKET_ID"])); if(!$obBucket->Init()) { $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_UPLOAD_ERROR', array('#errno#'=>1))); return false; } $arUploadInfo = unserialize($ar["NEXT_STEP"]); $bSuccess = $obBucket->GetService()->UploadPart( $obBucket->GetBucketArray(), $arUploadInfo, $data ); if (!$this->UpdateProgress($arUploadInfo, $bSuccess)) { $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_UPLOAD_ERROR', array('#errno#'=>2))); return false; } return $bSuccess; } return false; } /** * @param string $data * @param int $part_no * @return bool */ function Part($data, $part_no, $obBucket = null) { global $APPLICATION; if($this->isStarted()) { $ar = $this->GetArray(); if($obBucket == null) $obBucket = new CCloudStorageBucket(intval($ar["BUCKET_ID"])); if(!$obBucket->Init()) { $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_UPLOAD_ERROR', array('#errno#'=>3))); return false; } $service = $obBucket->GetService(); if (!is_callable(array($service, 'UploadPartNo'))) { $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_UPLOAD_ERROR', array('#errno#'=>4))); return false; } $arUploadInfo = unserialize($ar["NEXT_STEP"]); $bSuccess = $obBucket->GetService()->UploadPartNo( $obBucket->GetBucketArray(), $arUploadInfo, $data, $part_no ); if (!$this->UpdateProgress($arUploadInfo, $bSuccess)) { $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_UPLOAD_ERROR', array('#errno#'=>5))); return false; } return $bSuccess; } return false; } /** * @return bool */ function Finish($obBucket = null) { if($this->isStarted()) { $ar = $this->GetArray(); if($obBucket == null) $obBucket = new CCloudStorageBucket(intval($ar["BUCKET_ID"])); if(!$obBucket->Init()) return false; $arUploadInfo = unserialize($ar["NEXT_STEP"]); $bSuccess = $obBucket->GetService()->CompleteMultipartUpload( $obBucket->GetBucketArray(), $arUploadInfo ); if($bSuccess) $this->Delete(); $this->DeleteOld(); if ($bSuccess) { foreach(GetModuleEvents("clouds", "OnAfterCompleteMultipartUpload", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($obBucket, array("size" => $ar["FILE_SIZE"]), $this->_filePath)); } } return $bSuccess; } return false; } /** * @return int */ function GetPartCount() { $ar = $this->GetArray(); if(is_array($ar)) return intval($ar["PART_NO"]); else return 0; } /** * @return float */ function GetPos() { $ar = $this->GetArray(); if(is_array($ar)) return intval($ar["PART_NO"])*doubleval($ar["PART_SIZE"]); else return 0; } /** * @return int */ function getPartSize() { $ar = $this->GetArray(); if(is_array($ar)) return intval($ar["PART_SIZE"]); else return 0; } /** * @return bool */ function hasRetries() { $ar = $this->GetArray(); return is_array($ar) && (intval($ar["PART_FAIL_COUNTER"]) < $this->_max_retries); } /** * @return string */ function getTempFileName() { $ar = $this->GetArray(); if(is_array($ar)) return $ar["TMP_FILE"]; else return ""; } /** * @param array $arUploadInfo * @param boolean $bSuccess * @return boolean */ protected function UpdateProgress($arUploadInfo, $bSuccess) { global $DB; if ($bSuccess) { $arFields = array( "NEXT_STEP" => serialize($arUploadInfo), "~PART_NO" => "PART_NO + 1", "PART_FAIL_COUNTER" => 0, ); $arBinds = array( "NEXT_STEP" => $arFields["NEXT_STEP"], ); } else { $arFields = array( "~PART_FAIL_COUNTER" => "PART_FAIL_COUNTER + 1", ); $arBinds = array( ); } $strUpdate = $DB->PrepareUpdate("b_clouds_file_upload", $arFields); if ($strUpdate != "") { $strSql = "UPDATE b_clouds_file_upload SET ".$strUpdate." WHERE ID = '".$this->_ID."'"; if(!$DB->QueryBind($strSql, $arBinds)) { unset($this->_cache); return false; } } unset($this->_cache); return true; } } ?>classes/general/storage_service_s3.php000064400000066576150241560060014143 0ustar00<? IncludeModuleLangFile(__FILE__); class CCloudStorageService_AmazonS3 extends CCloudStorageService { protected $status = 0; protected $verb = ''; protected $host = ''; protected $url = ''; protected $headers =/*.(array[string]string).*/array(); protected $set_headers =/*.(array[string]string).*/array(); protected $errno = 0; protected $errstr = ''; protected $result = ''; protected $new_end_point = ''; protected $_public = true; protected $location = ''; /** * @return int */ function GetLastRequestStatus() { return $this->status; } /** * @return CCloudStorageService */ function GetObject() { return new CCloudStorageService_AmazonS3(); } /** * @return string */ function GetID() { return "amazon_s3"; } /** * @return string */ function GetName() { return "Amazon Simple Storage Service"; } /** * @return array[string]string */ function GetLocationList() { // http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region return array( "" => "US Standard", "us-east-2" => "US East (Ohio)", "us-west-1" => "US West (Northern California)", "us-west-2" => "US West (Oregon)", "ca-central-1" => "Canada (Central)", "ap-south-1" => "Asia Pacific (Mumbai)", "ap-northeast-2" => "Asia Pacific (Seoul)", "ap-southeast-1" => "Asia Pacific (Singapore)", "ap-southeast-2" => "Asia Pacific (Sydney)", "ap-northeast-1" => "Asia Pacific (Tokyo)", "eu-central-1" => "EU (Frankfurt)", "eu-west-1" => "EU (Ireland)", "eu-west-2" => "EU (London)", "sa-east-1" => "South America (Sao Paulo)", ); } /** * @return array[string]string */ function GetAPList() { // http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region return array( "" => "s3.amazonaws.com", "us-east-2" => "s3.us-east-2.amazonaws.com", "us-west-1" => "s3-us-west-1.amazonaws.com", "us-west-2" => "s3-us-west-2.amazonaws.com", "ca-central-1" => "s3.ca-central-1.amazonaws.com", "ap-south-1" => "s3.ap-south-1.amazonaws.com", "ap-northeast-2" => "s3.ap-northeast-2.amazonaws.com", "ap-southeast-1" => "s3-ap-southeast-1.amazonaws.com", "ap-southeast-2" => "s3-ap-southeast-2.amazonaws.com", "ap-northeast-1" => "s3-ap-northeast-1.amazonaws.com", "eu-central-1" => "s3.eu-central-1.amazonaws.com", "eu-west-1" => "s3-eu-west-1.amazonaws.com", "eu-west-2" => "s3.eu-west-2.amazonaws.com", "sa-east-1" => "South America (Sao Paulo)", ); } /** * @param array[string]string $arBucket * @param bool $bServiceSet * @param string $cur_SERVICE_ID * @param bool $bVarsFromForm * @return string */ function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm) { if($bVarsFromForm) $arSettings = $_POST["SETTINGS"][$this->GetID()]; else $arSettings = unserialize($arBucket["SETTINGS"]); if(!is_array($arSettings)) $arSettings = array("ACCESS_KEY" => "", "SECRET_KEY" => ""); $htmlID = htmlspecialcharsbx($this->GetID()); $result = ' <tr id="SETTINGS_0_'.$htmlID.'" style="display:'.($cur_SERVICE_ID === $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_S3_EDIT_ACCESS_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][ACCESS_KEY]" id="'.$htmlID.'ACCESS_KEY" value="'.htmlspecialcharsbx($arSettings['ACCESS_KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_ACCESS_KEY" id="'.$htmlID.'INP_ACCESS_KEY" value="'.htmlspecialcharsbx($arSettings['ACCESS_KEY']).'" '.($arBucket['READ_ONLY'] === 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'ACCESS_KEY\').value = this.value"></td> </tr> <tr id="SETTINGS_1_'.$htmlID.'" style="display:'.($cur_SERVICE_ID === $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_S3_EDIT_SECRET_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][SECRET_KEY]" id="'.$htmlID.'SECRET_KEY" value="'.htmlspecialcharsbx($arSettings['SECRET_KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_SECRET_KEY" id="'.$htmlID.'INP_SECRET_KEY" value="'.htmlspecialcharsbx($arSettings['SECRET_KEY']).'" autocomplete="off" '.($arBucket['READ_ONLY'] === 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'SECRET_KEY\').value = this.value"></td> </tr> <tr id="SETTINGS_2_'.$htmlID.'" style="display:'.($cur_SERVICE_ID === $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr"> <td> </td> <td>'.BeginNote().GetMessage("CLO_STORAGE_S3_EDIT_HELP").EndNote().'</td> </tr> '; return $result; } /** * @param array[string]string $arBucket * @param array[string]string $arSettings * @return bool */ function CheckSettings($arBucket, &$arSettings) { global $APPLICATION; $aMsg =/*.(array[int][string]string).*/array(); $result = array( "ACCESS_KEY" => is_array($arSettings)? trim($arSettings["ACCESS_KEY"]): '', "SECRET_KEY" => is_array($arSettings)? trim($arSettings["SECRET_KEY"]): '', ); if(is_array($arSettings) && array_key_exists("SESSION_TOKEN", $arSettings)) { $result["SESSION_TOKEN"] = trim($arSettings["SESSION_TOKEN"]); } if($arBucket["READ_ONLY"] !== "Y" && $result["ACCESS_KEY"] === '') { $aMsg[] = array( "id" => $this->GetID()."INP_ACCESS_KEY", "text" => GetMessage("CLO_STORAGE_S3_EMPTY_ACCESS_KEY"), ); } if($arBucket["READ_ONLY"] !== "Y" && $result["SECRET_KEY"] === '') { $aMsg[] = array( "id" => $this->GetID()."INP_SECRET_KEY", "text" => GetMessage("CLO_STORAGE_S3_EMPTY_SECRET_KEY"), ); } if(!empty($aMsg)) { $e = new CAdminException($aMsg); $APPLICATION->ThrowException($e); return false; } else { $arSettings = $result; } return true; } /** * @param string $data * @param string $key * @return string */ function hmacsha1($data, $key) { if(strlen($key)>64) $key=pack('H*', sha1($key)); $key = str_pad($key, 64, chr(0x00)); $ipad = str_repeat(chr(0x36), 64); $opad = str_repeat(chr(0x5c), 64); $hmac = pack('H*', sha1(($key^$opad).pack('H*', sha1(($key^$ipad).$data)))); return $hmac; } /** * @param array[string]string $arSettings * @param string $RequestMethod * @param string $bucket * @param string $RequestURI * @param string $ContentType * @param array[string]string $additional_headers * @param string $params * @param string|resource $content * @return array[string]string */ function SignRequest($arSettings, $RequestMethod, $bucket, $RequestURI, $ContentType, $additional_headers, $params = "", $content = "") { static $search = array("+", "="); static $replace = array("%20", "%3D"); $CanonicalizedResource = strlen($RequestURI)? str_replace($search, $replace, $RequestURI): "/"; $CanonicalQuery = explode("&", ltrim($params, "?")); sort($CanonicalQuery); $CanonicalQueryString = implode("&", $CanonicalQuery); $CanonicalHeaders = array(); foreach($additional_headers as $key => $value) { $key = strtolower($key); if (isset($CanonicalHeaders[$key])) $CanonicalHeaders[$key] .= ","; else $CanonicalHeaders[$key] = $key.":"; $CanonicalHeaders[$key] .= trim($value, " \t\n\r"); } ksort($CanonicalHeaders); $CanonicalHeadersString = implode("\n", $CanonicalHeaders); $SignedHeaders = implode(";", array_keys($CanonicalHeaders)); if (is_resource($content)) { $streamPosition = ftell($content); $hashResource = hash_init("sha256"); hash_update_stream($hashResource, $content); $HashedPayload = hash_final($hashResource); fseek($content, $streamPosition); } else { $HashedPayload = hash("sha256", $content, false); } $CanonicalRequest = ""; $CanonicalRequest .= $RequestMethod."\n"; $CanonicalRequest .= $CanonicalizedResource."\n"; $CanonicalRequest .= $CanonicalQueryString."\n"; $CanonicalRequest .= $CanonicalHeadersString."\n\n"; $CanonicalRequest .= $SignedHeaders."\n"; $CanonicalRequest .= $HashedPayload; $Algorithm = "AWS4-HMAC-SHA256"; $Time = time(); $RequestDate = gmdate('Ymd', $Time); $RequestTime = gmdate('Ymd', $Time).'T'.gmdate('His', $Time).'Z'; $Region = $this->location? $this->location: 'us-east-1'; $Service = "s3"; $Scope = $RequestDate."/".$Region."/".$Service."/aws4_request"; $StringToSign = ""; $StringToSign .= $Algorithm."\n"; $StringToSign .= $RequestTime."\n"; $StringToSign .= $Scope."\n"; $StringToSign .= hash("sha256", $CanonicalRequest, false); $kSecret = $arSettings["SECRET_KEY"]; $kDate = hash_hmac("sha256", $RequestDate, "AWS4".$kSecret, true); $kRegion = hash_hmac("sha256", $Region, $kDate, true); $kService = hash_hmac("sha256", $Service, $kRegion, true); $kSigning = hash_hmac("sha256", "aws4_request", $kService, true); $Signature = hash_hmac("sha256", $StringToSign, $kSigning, false); $Authorization = "$Algorithm Credential=$arSettings[ACCESS_KEY]/$Scope, SignedHeaders=$SignedHeaders, Signature=$Signature"; return array( "Date" => $RequestTime, "Authorization" => $Authorization, "x-amz-content-sha256" => $HashedPayload, ); } /** * @param string $location * @return void **/ function SetLocation($location) { if ($location) $this->location = $location; else $this->location = ""; } protected function GetRequestHost($bucket) { if( $this->new_end_point != "" && preg_match('#^(http|https)://'.preg_quote($bucket, '#').'(.+?)/#', $this->new_end_point, $match) > 0 ) { return $bucket.$match[2]; } elseif ($this->location) { return $bucket.".s3-".$this->location.".amazonaws.com"; } else { return $bucket.".s3.amazonaws.com"; } } /** * @param array[string]string $arSettings * @param string $verb * @param string $bucket * @param string $file_name * @param string $params * @param string $content * @param array[string]string $additional_headers * @return mixed */ function SendRequest($arSettings, $verb, $bucket, $file_name='/', $params='', $content='', $additional_headers=/*.(array[string]string).*/array()) { global $APPLICATION; $this->status = 0; $obRequest = new CHTTP; if (isset($additional_headers["option-file-result"])) { $obRequest->fp = $additional_headers["option-file-result"]; } if(isset($additional_headers["Content-Type"])) { $ContentType = $additional_headers["Content-Type"]; } else { $ContentType = $content != ""? 'text/plain': ''; } unset($additional_headers["Content-Type"]); foreach($this->set_headers as $key => $value) { $additional_headers[$key] = $value; } if(array_key_exists("SESSION_TOKEN", $arSettings)) { $additional_headers["x-amz-security-token"] = $arSettings["SESSION_TOKEN"]; } $additional_headers["host"] = $this->GetRequestHost($bucket); foreach($this->SignRequest($arSettings, $verb, $bucket, $file_name, $ContentType, $additional_headers, $params, $content) as $key => $value) { $obRequest->additional_headers[$key] = $value; } foreach($additional_headers as $key => $value) if(preg_match("/^(option-|host\$)/", $key) == 0) $obRequest->additional_headers[$key] = $value; $host = $additional_headers["host"]; $was_end_point = $this->new_end_point; $this->new_end_point = ''; $obRequest->Query($verb, $host, 80, $file_name.$params, $content, '', $ContentType); $this->status = $obRequest->status; $this->host = $host; $this->verb = $verb; $this->url = $file_name.$params; $this->headers = $obRequest->headers; $this->errno = $obRequest->errno; $this->errstr = $obRequest->errstr; $this->result = $obRequest->result; if($obRequest->status == 200) { if( isset($additional_headers["option-raw-result"]) || isset($additional_headers["option--result"]) ) { return $obRequest->result; } elseif($obRequest->result != "") { $obXML = new CDataXML; $text = preg_replace("/<"."\\?XML.*?\\?".">/i", "", $obRequest->result); if($obXML->LoadString($text)) { $arXML = $obXML->GetArray(); if(is_array($arXML)) { return $arXML; } } //XML parse error $e = new CApplicationException(GetMessage('CLO_STORAGE_S3_XML_PARSE_ERROR', array('#errno#'=>'1'))); $APPLICATION->ThrowException($e); return false; } else { //Empty success result return array(); } } elseif( $obRequest->status == 307 //Temporary redirect && isset($obRequest->headers["Location"]) && $was_end_point === "" //No recurse yet ) { $this->new_end_point = $obRequest->headers["Location"]; return $this->SendRequest( $arSettings, $verb, $bucket, $file_name, $params, $content, $additional_headers ); } elseif($obRequest->status > 0) { if($obRequest->result != "") { $obXML = new CDataXML; if($obXML->LoadString($obRequest->result)) { $node = $obXML->SelectNodes("/Error/Message"); if (is_object($node)) { $errorMessage = trim($node->textContent(), '.'); $e = new CApplicationException(GetMessage('CLO_STORAGE_S3_XML_ERROR', array( '#errmsg#' => $errorMessage, ))); $APPLICATION->ThrowException($e); return false; } } } $e = new CApplicationException(GetMessage('CLO_STORAGE_S3_XML_PARSE_ERROR', array('#errno#'=>'2'))); $APPLICATION->ThrowException($e); return false; } else { $e = new CApplicationException(GetMessage('CLO_STORAGE_S3_XML_PARSE_ERROR', array('#errno#'=>'3'))); $APPLICATION->ThrowException($e); return false; } } /** * @param array[string]string $arBucket * @return bool */ function CreateBucket($arBucket) { global $APPLICATION; $arFiles = $this->ListFiles($arBucket, '/'); if(is_array($arFiles)) return true; if($arBucket["LOCATION"] != "") $content = '<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'. '<LocationConstraint>'.$arBucket["LOCATION"].'</LocationConstraint>'. '</CreateBucketConfiguration>'; else $content = ''; $this->SetLocation($arBucket["LOCATION"]); $response = $this->SendRequest( $arBucket["SETTINGS"], 'PUT', $arBucket["BUCKET"], '/', '', $content ); if($this->status == 409/*Already exists*/) { $APPLICATION->ResetException(); return true; } else { return is_array($response); } } /** * @param array[string]string $arBucket * @return bool */ function DeleteBucket($arBucket) { global $APPLICATION; if($arBucket["PREFIX"] != "") { //Do not delete bucket if there is some files left if(!$this->IsEmptyBucket($arBucket)) return false; //Let's pretend we deleted the bucket return true; } $this->SetLocation($arBucket["LOCATION"]); $response = $this->SendRequest( $arBucket["SETTINGS"], 'DELETE', $arBucket["BUCKET"] ); if( $this->status == 204/*No content*/ || $this->status == 404/*Not exists*/ || $this->status == 403/*Access denied*/ ) { $APPLICATION->ResetException(); return true; } else { return is_array($response); } } /** * @param array[string]string $arBucket * @return bool */ function IsEmptyBucket($arBucket) { global $APPLICATION; $this->SetLocation($arBucket["LOCATION"]); $response = $this->SendRequest( $arBucket["SETTINGS"], 'GET', $arBucket["BUCKET"], '/', '?max-keys=1'.($arBucket["PREFIX"] != ""? '&prefix='.$arBucket["PREFIX"].'/': '') ); if($this->status == 404 || $this->status == 403) { $APPLICATION->ResetException(); return true; } elseif(is_array($response)) { return !isset($response["ListBucketResult"]) || !is_array($response["ListBucketResult"]) || !isset($response["ListBucketResult"]["#"]) || !is_array($response["ListBucketResult"]["#"]) || !isset($response["ListBucketResult"]["#"]["Contents"]) || !is_array($response["ListBucketResult"]["#"]["Contents"]); } else { return false; } } /** * @param array[string]string $arBucket * @param mixed $arFile * @return string */ function GetFileSRC($arBucket, $arFile) { $proto = CMain::IsHTTPS()? "https": "http"; static $aps = null; if (!$aps) $aps = self::GetAPList(); if($arBucket["CNAME"] != "") { $host = $arBucket["CNAME"]; $pref = ""; } elseif ($proto === "https" && strpos($arBucket["BUCKET"], ".") !== false) { if (isset($aps[$arBucket["LOCATION"]])) $host = $aps[$arBucket["LOCATION"]]; else $host = $aps[""]; $pref = $arBucket["BUCKET"]; } else { if (isset($aps[$arBucket["LOCATION"]])) $host = $arBucket["BUCKET"].".".$aps[$arBucket["LOCATION"]]; else $host = $aps[""]; $pref = ""; } if(is_array($arFile)) $URI = ltrim($arFile["SUBDIR"]."/".$arFile["FILE_NAME"], "/"); else $URI = ltrim($arFile, "/"); if ($arBucket["PREFIX"] != "") { if(substr($URI, 0, strlen($arBucket["PREFIX"])+1) !== $arBucket["PREFIX"]."/") $URI = $arBucket["PREFIX"]."/".$URI; } if ($pref !== "") { $URI = $pref."/".$URI; } return $proto."://$host/".CCloudUtil::URLEncode($URI, "UTF-8"); } /** * @param array[string]string $arBucket * @param string $filePath * @return bool */ function FileExists($arBucket, $filePath) { global $APPLICATION; if($arBucket["PREFIX"] != "") { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $this->SetLocation($arBucket["LOCATION"]); $this->SendRequest( $arBucket["SETTINGS"], 'HEAD', $arBucket["BUCKET"], $filePath ); if($this->status == 200) { if (isset($this->headers["Content-Length"]) && $this->headers["Content-Length"] > 0) return $this->headers["Content-Length"]; else return true; } elseif($this->status == 206) { $APPLICATION->ResetException(); return true; } else//if($this->status == 404) { $APPLICATION->ResetException(); return false; } } function FileCopy($arBucket, $arFile, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $additional_headers = array(); if($this->_public) $additional_headers["x-amz-acl"] = "public-read"; $additional_headers["x-amz-copy-source"] = CCloudUtil::URLEncode("/".$arBucket["BUCKET"]."/".($arBucket["PREFIX"]? $arBucket["PREFIX"]."/": "").($arFile["SUBDIR"]? $arFile["SUBDIR"]."/": "").$arFile["FILE_NAME"], "UTF-8"); $additional_headers["Content-Type"] = $arFile["CONTENT_TYPE"]; $this->SetLocation($arBucket["LOCATION"]); $this->SendRequest( $arBucket["SETTINGS"], 'PUT', $arBucket["BUCKET"], CCloudUtil::URLEncode($filePath, "UTF-8"), '', '', $additional_headers ); if($this->status == 200) { return $this->GetFileSRC($arBucket, $filePath); } else//if($this->status == 404) { $APPLICATION->ResetException(); return false; } } function DownloadToFile($arBucket, $arFile, $filePath) { $io = CBXVirtualIo::GetInstance(); $obRequest = new CHTTP; $obRequest->follow_redirect = true; return $obRequest->Download($this->GetFileSRC($arBucket, $arFile), $io->GetPhysicalName($filePath)); } function DeleteFile($arBucket, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $this->SetLocation($arBucket["LOCATION"]); $this->SendRequest( $arBucket["SETTINGS"], 'DELETE', $arBucket["BUCKET"], $filePath ); if($this->status == 204) { $APPLICATION->ResetException(); return true; } else//if($this->status == 404) { $APPLICATION->ResetException(); return false; } } function SaveFile($arBucket, $filePath, $arFile) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $additional_headers = array(); if($this->_public) $additional_headers["x-amz-acl"] = "public-read"; $additional_headers["Content-Type"] = $arFile["type"]; $additional_headers["Content-Length"] = (array_key_exists("content", $arFile)? CUtil::BinStrlen($arFile["content"]): filesize($arFile["tmp_name"])); $this->SetLocation($arBucket["LOCATION"]); $this->SendRequest( $arBucket["SETTINGS"], 'PUT', $arBucket["BUCKET"], $filePath, '', (array_key_exists("content", $arFile)? $arFile["content"]: fopen($arFile["tmp_name"], "rb")), $additional_headers ); if($this->status == 200) { return true; } elseif ($this->status == 400 && strpos($this->result, 'ExpiredToken') !== false) { $this->tokenHasExpired = true; return false; } elseif($this->status == 403) { AddMessage2Log($this); return false; } else { AddMessage2Log($this); $APPLICATION->ResetException(); return false; } } function ListFiles($arBucket, $filePath, $bRecursive = false) { global $APPLICATION; $result = array( "dir" => array(), "file" => array(), "file_size" => array(), ); $filePath = trim($filePath, '/'); if(strlen($filePath)) $filePath .= '/'; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = $arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = $APPLICATION->ConvertCharset($filePath, LANG_CHARSET, "UTF-8"); $this->SetLocation($arBucket["LOCATION"]); $marker = ''; while(true) { $response = $this->SendRequest( $arBucket["SETTINGS"], 'GET', $arBucket["BUCKET"], '/', '?'.($bRecursive? '': 'delimiter=%2F&').'prefix='.urlencode($filePath) .'&marker='.str_replace("+", "%20", urlencode($marker)) ); if( $this->status == 200 && is_array($response) && isset($response["ListBucketResult"]) && is_array($response["ListBucketResult"]) && isset($response["ListBucketResult"]["#"]) && is_array($response["ListBucketResult"]["#"]) ) { if( isset($response["ListBucketResult"]["#"]["CommonPrefixes"]) && is_array($response["ListBucketResult"]["#"]["CommonPrefixes"]) ) { foreach($response["ListBucketResult"]["#"]["CommonPrefixes"] as $a) { $dir_name = substr(rtrim($a["#"]["Prefix"][0]["#"], "/"), strlen($filePath)); $result["dir"][] = $APPLICATION->ConvertCharset(urldecode($dir_name), "UTF-8", LANG_CHARSET); } } $lastKey = null; if( isset($response["ListBucketResult"]["#"]["Contents"]) && is_array($response["ListBucketResult"]["#"]["Contents"]) ) { foreach($response["ListBucketResult"]["#"]["Contents"] as $a) { $file_name = substr($a["#"]["Key"][0]["#"], strlen($filePath)); $result["file"][] = $APPLICATION->ConvertCharset($file_name, "UTF-8", LANG_CHARSET); $result["file_size"][] = $a["#"]["Size"][0]["#"]; $lastKey = $a["#"]["Key"][0]["#"]; } } if( isset($response["ListBucketResult"]["#"]["IsTruncated"]) && is_array($response["ListBucketResult"]["#"]["IsTruncated"]) && $response["ListBucketResult"]["#"]["IsTruncated"][0]["#"] === "true" ) { if (strlen($response["ListBucketResult"]["#"]["NextMarker"][0]["#"]) > 0) { $marker = $response["ListBucketResult"]["#"]["NextMarker"][0]["#"]; continue; } elseif ($lastKey !== null); { $marker = $lastKey; continue; } } break; } elseif ($this->status == 400 && strpos($this->result, 'ExpiredToken') !== false) { $this->tokenHasExpired = true; return false; } else { return false; } } return $result; } function InitiateMultipartUpload($arBucket, &$NS, $filePath, $fileSize, $ContentType) { $filePath = '/'.trim($filePath, '/'); if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"].$filePath; } $filePathU = CCloudUtil::URLEncode($filePath, "UTF-8"); $additional_headers = array(); if($this->_public) $additional_headers["x-amz-acl"] = "public-read"; $additional_headers["Content-Type"] = $ContentType; $this->SetLocation($arBucket["LOCATION"]); $response = $this->SendRequest( $arBucket["SETTINGS"], 'POST', $arBucket["BUCKET"], $filePathU, '?uploads=', '', $additional_headers ); if( $this->status == 200 && is_array($response) && isset($response["InitiateMultipartUploadResult"]) && is_array($response["InitiateMultipartUploadResult"]) && isset($response["InitiateMultipartUploadResult"]["#"]) && is_array($response["InitiateMultipartUploadResult"]["#"]) && isset($response["InitiateMultipartUploadResult"]["#"]["UploadId"]) && is_array($response["InitiateMultipartUploadResult"]["#"]["UploadId"]) && isset($response["InitiateMultipartUploadResult"]["#"]["UploadId"][0]) && is_array($response["InitiateMultipartUploadResult"]["#"]["UploadId"][0]) && isset($response["InitiateMultipartUploadResult"]["#"]["UploadId"][0]["#"]) && is_string($response["InitiateMultipartUploadResult"]["#"]["UploadId"][0]["#"]) ) { $NS = array( "filePath" => $filePath, "UploadId" => $response["InitiateMultipartUploadResult"]["#"]["UploadId"][0]["#"], "Parts" => array(), ); return true; } else { return false; } } function GetMinUploadPartSize() { return BX_S3_MIN_UPLOAD_PART_SIZE; } function UploadPartNo($arBucket, &$NS, $data, $part_no) { $filePath = '/'.trim($NS["filePath"], '/'); if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"].$filePath; } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $this->SetLocation($arBucket["LOCATION"]); $this->SendRequest( $arBucket["SETTINGS"], 'PUT', $arBucket["BUCKET"], $filePath, '?partNumber='.($part_no + 1).'&uploadId='.urlencode($NS["UploadId"]), $data ); if($this->status == 200 && is_array($this->headers)) { foreach ($this->headers as $key => $value) { if (strtolower($key) === "etag") { $NS["Parts"][$part_no] = $value; return true; } } } return false; } function UploadPart($arBucket, &$NS, $data) { return $this->UploadPartNo($arBucket, $NS, $data, count($NS["Parts"])); } function CompleteMultipartUpload($arBucket, &$NS) { $filePath = '/'.trim($NS["filePath"], '/'); if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"].$filePath; } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); ksort($NS["Parts"]); $data = ""; foreach($NS["Parts"] as $PartNumber => $ETag) { $data .= "<Part><PartNumber>".($PartNumber+1)."</PartNumber><ETag>".$ETag."</ETag></Part>\n"; } $this->SetLocation($arBucket["LOCATION"]); $this->SendRequest( $arBucket["SETTINGS"], 'POST', $arBucket["BUCKET"], $filePath, '?uploadId='.urlencode($NS["UploadId"]), "<CompleteMultipartUpload>".$data."</CompleteMultipartUpload>" ); return $this->status == 200; } function setPublic($state = true) { $this->_public = $state !== false; } function setHeader($key, $value) { $this->set_headers[$key] = $value; } function unsetHeader($key) { unset($this->set_headers[$key]); } function getHeaders() { return $this->headers; } } classes/general/storage_service_openstack.php000064400000044554150241560060015575 0ustar00<? IncludeModuleLangFile(__FILE__); class CCloudStorageService_OpenStackStorage extends CCloudStorageService { protected $status = 0; protected $errno = 0; protected $errstr = ''; protected $result = ''; protected $verb = ''; protected $url = ''; function GetLastRequestStatus() { return $this->status; } function GetObject() { return new CCloudStorageService_OpenStackStorage(); } function GetID() { return "openstack_storage"; } function GetName() { return "OpenStack Object Storage"; } function GetLocationList() { return array( "" => "N/A", ); } function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm) { if($bVarsFromForm) $arSettings = $_POST["SETTINGS"][$this->GetID()]; else $arSettings = unserialize($arBucket["SETTINGS"]); if(!is_array($arSettings)) { $arSettings = array( "HOST" => "", "USER" => "", "KEY" => "", "FORCE_HTTP" => "N", ); } $htmlID = htmlspecialcharsbx($this->GetID()); $show = (($cur_SERVICE_ID == $this->GetID()) || !$bServiceSet)? '': 'none'; $result = ' <tr id="SETTINGS_2_'.$htmlID.'" style="display:'.$show.'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_OPENSTACK_EDIT_HOST").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][HOST]" id="'.$htmlID.'HOST" value="'.htmlspecialcharsbx($arSettings['HOST']).'"><input type="text" size="55" name="'.$htmlID.'INP_HOST" id="'.$htmlID.'INP_HOST" value="'.htmlspecialcharsbx($arSettings['HOST']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'HOST\').value = this.value"></td> </tr> <tr id="SETTINGS_0_'.$htmlID.'" style="display:'.$show.'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_OPENSTACK_EDIT_USER").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][USER]" id="'.$htmlID.'USER" value="'.htmlspecialcharsbx($arSettings['USER']).'"><input type="text" size="55" name="'.$htmlID.'INP_" id="'.$htmlID.'INP_USER" value="'.htmlspecialcharsbx($arSettings['USER']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'USER\').value = this.value"></td> </tr> <tr id="SETTINGS_1_'.$htmlID.'" style="display:'.$show.'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_OPENSTACK_EDIT_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][KEY]" id="'.$htmlID.'KEY" value="'.htmlspecialcharsbx($arSettings['KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_KEY" id="'.$htmlID.'INP_KEY" value="'.htmlspecialcharsbx($arSettings['KEY']).'" autocomplete="off" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'KEY\').value = this.value"></td> </tr> <tr id="SETTINGS_3_'.$htmlID.'" style="display:'.$show.'" class="settings-tr"> <td>'.GetMessage("CLO_STORAGE_OPENSTACK_FORCE_HTTP").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][FORCE_HTTP]" id="'.$htmlID.'KEY" value="N"><input type="checkbox" name="SETTINGS['.$htmlID.'][FORCE_HTTP]" id="'.$htmlID.'FORCE_HTTP" value="Y" '.($arSettings['FORCE_HTTP'] == 'Y'? 'checked="checked"': '').'></td> </tr> '; return $result; } function CheckSettings($arBucket, &$arSettings) { global $APPLICATION; $aMsg = array(); $result = array( "HOST" => is_array($arSettings)? trim($arSettings["HOST"]): '', "USER" => is_array($arSettings)? trim($arSettings["USER"]): '', "KEY" => is_array($arSettings)? trim($arSettings["KEY"]): '', "FORCE_HTTP" => is_array($arSettings) && $arSettings["FORCE_HTTP"] == "Y"? "Y": "N", ); if($arBucket["READ_ONLY"] !== "Y" && !strlen($result["HOST"])) $aMsg[] = array("id" => $this->GetID()."INP_HOST", "text" => GetMessage("CLO_STORAGE_OPENSTACK_EMPTY_HOST")); if($arBucket["READ_ONLY"] !== "Y" && !strlen($result["USER"])) $aMsg[] = array("id" => $this->GetID()."INP_USER", "text" => GetMessage("CLO_STORAGE_OPENSTACK_EMPTY_USER")); if($arBucket["READ_ONLY"] !== "Y" && !strlen($result["KEY"])) $aMsg[] = array("id" => $this->GetID()."INP_KEY", "text" => GetMessage("CLO_STORAGE_OPENSTACK_EMPTY_KEY")); if(empty($aMsg)) { if(!$this->_GetToken($result["HOST"], $result["USER"], $result["KEY"])) $aMsg[] = array("text" => GetMessage("CLO_STORAGE_OPENSTACK_ERROR_GET_TOKEN")); } if(!empty($aMsg)) { $e = new CAdminException($aMsg); $APPLICATION->ThrowException($e); return false; } else { $arSettings = $result; } return true; } function _GetToken($host, $user, $key) { global $APPLICATION; static $results = array(); $cache_id = "v0|".$host."|".$user."|".$key; if(array_key_exists($cache_id, $results)) { $result = $results[$cache_id]; } else { $result = false; $obCache = new CPHPCache; if($obCache->InitCache(600, $cache_id, "/")) /*TODO make setting*/ { $result = $obCache->GetVars(); } else { $obRequest = new CHTTP; $obRequest->additional_headers["X-Auth-User"] = $user; $obRequest->additional_headers["X-Auth-Key"] = $key; $obRequest->Query("GET", $host, 80, "/v1.0"); if($obRequest->status == 412) { $APPLICATION->ResetException(); $obRequest = new CHTTP; $obRequest->additional_headers["X-Auth-User"] = $user; $obRequest->additional_headers["X-Auth-Key"] = $key; $obRequest->Query("GET", $host, 80, "/auth/v1.0"); } if($obRequest->status == 204 || $obRequest->status == 200) { $arStorage = array(); if(preg_match("#^http://(.*?)(|:\d+)(/.*)\$#", $obRequest->headers["X-Storage-Url"], $arStorage)) { $result = $obRequest->headers; $result["X-Storage-NoProtoUrl"] = $arStorage[1].($arStorage[2] == ':80'? '': $arStorage[2]).$arStorage[3]; $result["X-Storage-Host"] = $arStorage[1]; $result["X-Storage-Port"] = $arStorage[2]? substr($arStorage[2], 1): 80; $result["X-Storage-Urn"] = $arStorage[3]; $result["X-Storage-Proto"] = ""; } } } if(is_array($result)) { if($obCache->StartDataCache()) $obCache->EndDataCache($result); } $results[$cache_id] = $result; } return $result; } function SendRequest($settings, $verb, $bucket, $file_name='', $params='', $content=false, $additional_headers=array()) { $arToken = $this->_GetToken($settings["HOST"], $settings["USER"], $settings["KEY"]); if(!$arToken) return false; $this->status = 0; $obRequest = new CHTTP; $RequestURI = $file_name; $ContentType = "N"; $obRequest->additional_headers["X-Auth-Token"] = $arToken["X-Auth-Token"]; foreach($additional_headers as $key => $value) { if($key == "Content-Type") $ContentType = $value; else $obRequest->additional_headers[$key] = $value; } @$obRequest->Query( $this->verb = $verb, $arToken["X-Storage-Host"], $arToken["X-Storage-Port"], $this->url = $arToken["X-Storage-Urn"]."/".$bucket.$RequestURI.$params, $content, $arToken["X-Storage-Proto"], $ContentType ); $this->status = $obRequest->status; $this->errno = $obRequest->errno; $this->errstr = $obRequest->errstr; $this->result = $obRequest->result; return $obRequest; } function CreateBucket($arBucket) { global $APPLICATION; $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], '', //filename '', //params false, //content array( "X-Container-Read" => ".r:*", "X-Container-Meta-Web-Listings" => "false", "X-Container-Meta-Type" => "public", ) ); return ($this->status == 201)/*Created*/ || ($this->status == 202) /*Accepted*/; } function DeleteBucket($arBucket) { global $APPLICATION; if($arBucket["PREFIX"]) { //Do not delete bucket if there is some files left if(!$this->IsEmptyBucket($arBucket)) return false; //Do not delete bucket if there is some files left in other prefixes $arAllBucket = $arBucket; $arBucket["PREFIX"] = ""; if(!$this->IsEmptyBucket($arAllBucket)) return true; } $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "DELETE", $arBucket["BUCKET"] ); if( $this->status == 204/*No Content*/ || $this->status == 404/*Not Found*/ ) { return true; } else { return false; } } function IsEmptyBucket($arBucket) { global $APPLICATION; $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "GET", $arBucket["BUCKET"], '', "?limit=1&format=xml".($arBucket["PREFIX"]? '&prefix='.$arBucket["PREFIX"]: '') ); $arXML = false; if(is_object($obRequest) && $obRequest->result) { $obXML = new CDataXML; $text = preg_replace("/<"."\\?XML.*?\\?".">/i", "", $obRequest->result); if($obXML->LoadString($text)) { $arXML = $obXML->GetArray(); } } if($this->status == 404) { return true; } elseif(is_array($arXML)) { return !isset($arXML["container"]) || !is_array($arXML["container"]) || !isset($arXML["container"]["#"]) || !is_array($arXML["container"]["#"]) || !isset($arXML["container"]["#"]["object"]) || !is_array($arXML["container"]["#"]["object"]); } else { return false; } } function GetFileSRC($arBucket, $arFile) { global $APPLICATION; if ($arBucket["SETTINGS"]["FORCE_HTTP"] === "Y") $proto = "http"; else $proto = ($APPLICATION->IsHTTPS()? "https": "http"); if($arBucket["CNAME"]) { $host = $proto."://".$arBucket["CNAME"]; } else { $arToken = $this->_GetToken( $arBucket["SETTINGS"]["HOST"], $arBucket["SETTINGS"]["USER"], $arBucket["SETTINGS"]["KEY"] ); if(is_array($arToken)) { if ($arToken["X-Storage-NoProtoUrl"]) $host = $proto."://".$arToken["X-Storage-NoProtoUrl"]."/".$arBucket["BUCKET"]; else $host = $arToken["X-Storage-Url"]."/".$arBucket["BUCKET"]; } else { return "/404.php"; } } if(is_array($arFile)) $URI = ltrim($arFile["SUBDIR"]."/".$arFile["FILE_NAME"], "/"); else $URI = ltrim($arFile, "/"); if($arBucket["PREFIX"]) { if(substr($URI, 0, strlen($arBucket["PREFIX"])+1) !== $arBucket["PREFIX"]."/") $URI = $arBucket["PREFIX"]."/".$URI; } return $host."/".CCloudUtil::URLEncode($URI, "UTF-8"); } function FileExists($arBucket, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "HEAD", $arBucket["BUCKET"], $filePath ); return ($this->status == 200 || $this->status == 206); } function FileCopy($arBucket, $arFile, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], CCloudUtil::URLEncode($filePath, "UTF-8"), '', false, array( "X-Copy-From" => CCloudUtil::URLEncode("/".$arBucket["BUCKET"]."/".($arBucket["PREFIX"]? $arBucket["PREFIX"]."/": "").($arFile["SUBDIR"]? $arFile["SUBDIR"]."/": "").$arFile["FILE_NAME"], "UTF-8"), ) ); if($this->status == 200 || $this->status == 201) return $this->GetFileSRC($arBucket, $filePath); else return false; } function DownloadToFile($arBucket, $arFile, $filePath) { $io = CBXVirtualIo::GetInstance(); $obRequest = new CHTTP; $obRequest->follow_redirect = true; return $obRequest->Download($this->GetFileSRC($arBucket, $arFile), $io->GetPhysicalName($filePath)); } function DeleteFile($arBucket, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "DELETE", $arBucket["BUCKET"], $filePath ); return ($obRequest->status == 204 || $obRequest->status == 404); } function SaveFile($arBucket, $filePath, $arFile) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); if (array_key_exists("content", $arFile)) { $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], $filePath, "", $arFile["content"], array( "Content-Type" => $arFile["type"], "Content-Length" => CUtil::BinStrlen($arFile["content"]), ) ); } else { $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], $filePath, "", fopen($arFile["tmp_name"], "rb"), array( "Content-Type" => $arFile["type"], "Content-Length" => filesize($arFile["tmp_name"]), ) ); } if($obRequest->status == 201) { return true; } else { return false; } } function ListFiles($arBucket, $filePath, $bRecursive = false) { global $APPLICATION; $result = array( "dir" => array(), "file" => array(), "file_size" => array(), ); $filePath = trim($filePath, '/'); if(strlen($filePath)) $filePath .= '/'; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = $arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = $APPLICATION->ConvertCharset($filePath, LANG_CHARSET, "UTF-8"); $marker = ''; $new_marker = false; while(true) { $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "GET", $arBucket["BUCKET"], '/', $s='?format=xml&'.($bRecursive? '': '&delimiter=/').'&prefix='.urlencode($filePath).'&marker='.urlencode($marker) ); $bFound = false; if(is_object($obRequest) && $obRequest->result && $this->status == 200) { $obXML = new CDataXML; $text = preg_replace("/<"."\\?XML.*?\\?".">/i", "", $obRequest->result); if($obXML->LoadString($text)) { $arXML = $obXML->GetArray(); if( isset($arXML["container"]) && is_array($arXML["container"]) && isset($arXML["container"]["#"]) && is_array($arXML["container"]["#"]) && !empty($arXML["container"]["#"]) ) { if( isset($arXML["container"]["#"]["object"]) && is_array($arXML["container"]["#"]["object"]) && !empty($arXML["container"]["#"]["object"]) ) { $bFound = true; foreach($arXML["container"]["#"]["object"] as $a) { $new_marker = $a["#"]["name"][0]["#"]; if($a["#"]["content_type"][0]["#"] === "application/directory") { $dir_name = trim(substr($a["#"]["name"][0]["#"], strlen($filePath)), "/"); $result["dir"][$APPLICATION->ConvertCharset(urldecode($dir_name), "UTF-8", LANG_CHARSET)] = true; } else { $file_name = substr($a["#"]["name"][0]["#"], strlen($filePath)); $file_name = $APPLICATION->ConvertCharset(urldecode($file_name), "UTF-8", LANG_CHARSET); if (!in_array($file_name, $result["file"])) { $result["file"][] = $file_name; $result["file_size"][] = $a["#"]["bytes"][0]["#"]; } } } } if( isset($arXML["container"]["#"]["subdir"]) && is_array($arXML["container"]["#"]["subdir"]) && !empty($arXML["container"]["#"]["subdir"]) ) { $bFound = true; foreach($arXML["container"]["#"]["subdir"] as $a) { $new_marker = $a["@"]["name"]; $dir_name = trim(substr($a["@"]["name"], strlen($filePath)), "/"); $result["dir"][$APPLICATION->ConvertCharset(urldecode($dir_name), "UTF-8", LANG_CHARSET)] = true; } } } } } else { return false; } if($new_marker === $marker) break; if(!$bFound) break; $marker = $new_marker; } $result["dir"] = array_keys($result["dir"]); return $result; } function InitiateMultipartUpload($arBucket, &$NS, $filePath, $fileSize, $ContentType) { $filePath = '/'.trim($filePath, '/'); if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"].$filePath; } $NS = array( "filePath" => $filePath, "fileTemp" => CCloudStorage::translit("/tmp".str_replace(' ', '_', $filePath), "/"), "partsCount" => 0, "Parts" => array(), "Content-Type" => $ContentType, ); return true; } function GetMinUploadPartSize() { return 5*1024*1024; //5MB } function UploadPartNo($arBucket, &$NS, $data, $part_no) { $filePath = $NS["fileTemp"]."/".sprintf("%06d", $part_no + 1); $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], $filePath, "", $data ); if(is_object($obRequest) && $this->status == 201) { $NS["partsCount"]++; $NS["Parts"][$part_no] = $filePath; return true; } else { return false; } } function UploadPart($arBucket, &$NS, $data) { return $this->UploadPartNo($arBucket, $NS, $data, count($NS["Parts"])); } function CompleteMultipartUpload($arBucket, &$NS) { $filePath = CCloudUtil::URLEncode($NS["fileTemp"], "UTF-8"); $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], $filePath, "", false, array( "Content-Type" => $NS["Content-Type"], "X-Object-Manifest" => $arBucket["BUCKET"].$filePath."/", ) ); if(is_object($obRequest) && $this->status == 201) { $obRequest = $this->SendRequest( $arBucket["SETTINGS"], "PUT", $arBucket["BUCKET"], CCloudUtil::URLEncode($NS["filePath"], "UTF-8"), '', false, array( "Content-Type" => $NS["Content-Type"], "X-Copy-From" => "/".$arBucket["BUCKET"].$filePath, ) ); if( is_object($obRequest) && ( $this->status == 201 || $this->status == 200 ) ) $result = true; else $result = false; $this->DeleteFile($arBucket, $NS["fileTemp"]); ksort($NS["Parts"]); foreach ($NS["Parts"] as $tmpPath) { $this->DeleteFile($arBucket, $tmpPath); } return $result; } else { //May be delete uploaded tmp file? return false; } } } ?>classes/general/util.php000064400000001074150241560060011305 0ustar00<? class CCloudUtil { /** * @param string $str * @param string $charset * @return string */ public static function URLEncode($str, $charset) { global $APPLICATION; $strEncodedURL = ''; $arUrlComponents = preg_split("#(://|/|\\?|=|&)#", $str, -1, PREG_SPLIT_DELIM_CAPTURE); foreach($arUrlComponents as $i => $part_of_url) { if((intval($i) % 2) == 1) $strEncodedURL .= (string)$part_of_url; else $strEncodedURL .= urlencode($APPLICATION->ConvertCharset(urldecode($part_of_url), LANG_CHARSET, $charset)); } return $strEncodedURL; } } ?>classes/general/storage_service_google.php000064400000056417150241560060015063 0ustar00<? IncludeModuleLangFile(__FILE__); class CCloudStorageService_GoogleStorage extends CCloudStorageService { protected $status = 0; protected $headers = array(); protected $errno = 0; protected $errstr = ''; protected $result = ''; protected $new_end_point; function GetLastRequestStatus() { return $this->status; } function GetObject() { return new CCloudStorageService_GoogleStorage(); } function GetID() { return "google_storage"; } function GetName() { return "Google Storage"; } function GetLocationList() { return array( "EU" => "Europe", "US" => "United States", ); } function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm) { if($bVarsFromForm) $arSettings = $_POST["SETTINGS"][$this->GetID()]; else $arSettings = unserialize($arBucket["SETTINGS"]); if(!is_array($arSettings)) $arSettings = array("PROJECT_ID" => "", "ACCESS_KEY" => "", "SECRET_KEY" => ""); $htmlID = htmlspecialcharsbx($this->GetID()); $result = ' <tr id="SETTINGS_0_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_GOOGLE_EDIT_PROJECT_ID").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][PROJECT_ID]" id="'.$htmlID.'PROJECT_ID" value="'.htmlspecialcharsbx($arSettings['PROJECT_ID']).'"><input type="text" size="55" name="'.$htmlID.'INP_" id="'.$htmlID.'INP_PROJECT_ID" value="'.htmlspecialcharsbx($arSettings['PROJECT_ID']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'PROJECT_ID\').value = this.value"></td> </tr> <tr id="SETTINGS_1_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_GOOGLE_EDIT_ACCESS_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][ACCESS_KEY]" id="'.$htmlID.'ACCESS_KEY" value="'.htmlspecialcharsbx($arSettings['ACCESS_KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_ACCESS_KEY" id="'.$htmlID.'INP_ACCESS_KEY" value="'.htmlspecialcharsbx($arSettings['ACCESS_KEY']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'ACCESS_KEY\').value = this.value"></td> </tr> <tr id="SETTINGS_2_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_GOOGLE_EDIT_SECRET_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][SECRET_KEY]" id="'.$htmlID.'SECRET_KEY" value="'.htmlspecialcharsbx($arSettings['SECRET_KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_SECRET_KEY" id="'.$htmlID.'INP_SECRET_KEY" value="'.htmlspecialcharsbx($arSettings['SECRET_KEY']).'" autocomplete="off" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'SECRET_KEY\').value = this.value"></td> </tr> <tr id="SETTINGS_3_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr"> <td> </td> <td>'.BeginNote().GetMessage("CLO_STORAGE_GOOGLE_EDIT_HELP").EndNote().'</td> </tr> '; return $result; } function CheckSettings($arBucket, &$arSettings) { global $APPLICATION; $aMsg = array(); $result = array( "PROJECT_ID" => is_array($arSettings)? trim($arSettings["PROJECT_ID"]): '', "ACCESS_KEY" => is_array($arSettings)? trim($arSettings["ACCESS_KEY"]): '', "SECRET_KEY" => is_array($arSettings)? trim($arSettings["SECRET_KEY"]): '', ); if($arBucket["READ_ONLY"] !== "Y" && !strlen($result["PROJECT_ID"])) $aMsg[] = array("id" => $this->GetID()."INP_PROJECT_ID", "text" => GetMessage("CLO_STORAGE_GOOGLE_EMPTY_PROJECT_ID")); if($arBucket["READ_ONLY"] !== "Y" && !strlen($result["ACCESS_KEY"])) $aMsg[] = array("id" => $this->GetID()."INP_ACCESS_KEY", "text" => GetMessage("CLO_STORAGE_GOOGLE_EMPTY_ACCESS_KEY")); if($arBucket["READ_ONLY"] !== "Y" && !strlen($result["SECRET_KEY"])) $aMsg[] = array("id" => $this->GetID()."INP_SECRET_KEY", "text" => GetMessage("CLO_STORAGE_GOOGLE_EMPTY_SECRET_KEY")); if(!empty($aMsg)) { $e = new CAdminException($aMsg); $APPLICATION->ThrowException($e); return false; } else { $arSettings = $result; } return true; } function CreateBucket($arBucket) { global $APPLICATION; if($arBucket["LOCATION"]) $content = '<CreateBucketConfiguration>'. '<LocationConstraint>'.$arBucket["LOCATION"].'</LocationConstraint>'. '</CreateBucketConfiguration>'; else $content = ''; $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'PUT', $arBucket["BUCKET"], '/', '', $content, array( "x-goog-project-id" => $arBucket["SETTINGS"]["PROJECT_ID"], ) ); if($this->status == 409/*Already exists*/) { $APPLICATION->ResetException(); return true; } else { return is_array($response); } } function DeleteBucket($arBucket) { global $APPLICATION; if($arBucket["PREFIX"]) { //Do not delete bucket if there is some files left if(!$this->IsEmptyBucket($arBucket)) return false; //Do not delete bucket if there is some files left in other prefixes $arAllBucket = $arBucket; $arBucket["PREFIX"] = ""; if(!$this->IsEmptyBucket($arAllBucket)) return true; } $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'DELETE', $arBucket["BUCKET"] ); if($this->status == 204/*No content*/ || $this->status == 404/*Not exists*/) { $APPLICATION->ResetException(); return true; } else { return is_array($response); } } function IsEmptyBucket($arBucket) { global $APPLICATION; $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'GET', $arBucket["BUCKET"], '/', '?max-keys=1'.($arBucket["PREFIX"]? '&prefix='.$arBucket["PREFIX"]: '') ); if($this->status == 404) { $APPLICATION->ResetException(); return true; } elseif(is_array($response)) { return !isset($response["ListBucketResult"]) || !is_array($response["ListBucketResult"]) || !isset($response["ListBucketResult"]["#"]) || !is_array($response["ListBucketResult"]["#"]) || !isset($response["ListBucketResult"]["#"]["Contents"]) || !is_array($response["ListBucketResult"]["#"]["Contents"]); } else { return false; } } function GetFileSRC($arBucket, $arFile) { global $APPLICATION; if($arBucket["CNAME"]) { $host = $arBucket["CNAME"]; } else { switch($arBucket["LOCATION"]) { case "EU": $host = $arBucket["BUCKET"].".commondatastorage.googleapis.com"; break; case "US": $host = $arBucket["BUCKET"].".commondatastorage.googleapis.com"; break; default: $host = $arBucket["BUCKET"].".commondatastorage.googleapis.com"; break; } } if(is_array($arFile)) $URI = ltrim($arFile["SUBDIR"]."/".$arFile["FILE_NAME"], "/"); else $URI = ltrim($arFile, "/"); if($arBucket["PREFIX"]) { if(substr($URI, 0, strlen($arBucket["PREFIX"])+1) !== $arBucket["PREFIX"]."/") $URI = $arBucket["PREFIX"]."/".$URI; } $proto = $APPLICATION->IsHTTPS()? "https": "http"; return $proto."://$host/".CCloudUtil::URLEncode($URI, "UTF-8"); } function FileExists($arBucket, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'HEAD', $arBucket["BUCKET"], $filePath ); if($this->status == 200) { return true; } elseif($this->status == 206) { $APPLICATION->ResetException(); return true; } else//if($this->status == 404) { $APPLICATION->ResetException(); return false; } } function FileCopy($arBucket, $arFile, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'PUT', $arBucket["BUCKET"], CCloudUtil::URLEncode($filePath, "UTF-8"), '', '', array( "x-goog-acl"=>"public-read", "x-goog-copy-source"=>CCloudUtil::URLEncode("/".$arBucket["BUCKET"]."/".($arBucket["PREFIX"]? $arBucket["PREFIX"]."/": "").($arFile["SUBDIR"]? $arFile["SUBDIR"]."/": "").$arFile["FILE_NAME"], "UTF-8"), "Content-Type"=>$arFile["CONTENT_TYPE"] ) ); if($this->status == 200) { return $this->GetFileSRC($arBucket, $filePath); } else//if($this->status == 404) { $APPLICATION->ResetException(); return false; } } function DownloadToFile($arBucket, $arFile, $filePath) { $io = CBXVirtualIo::GetInstance(); $obRequest = new CHTTP; $obRequest->follow_redirect = true; return $obRequest->Download($this->GetFileSRC($arBucket, $arFile), $io->GetPhysicalName($filePath)); } function DeleteFile($arBucket, $filePath) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'DELETE', $arBucket["BUCKET"], $filePath ); if($this->status == 204 || $this->status == 404) { $APPLICATION->ResetException(); return true; } else { $APPLICATION->ResetException(); return false; } } function SaveFile($arBucket, $filePath, $arFile) { global $APPLICATION; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = CCloudUtil::URLEncode($filePath, "UTF-8"); $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'PUT', $arBucket["BUCKET"], $filePath, '', (array_key_exists("content", $arFile)? $arFile["content"]: fopen($arFile["tmp_name"], "rb")), array( "x-goog-acl" => "public-read", "Content-Type" => $arFile["type"], "Content-Length" => (array_key_exists("content", $arFile)? CUtil::BinStrlen($arFile["content"]): filesize($arFile["tmp_name"])), ) ); if($this->status == 200) { return true; } else { $APPLICATION->ResetException(); return false; } } function ListFiles($arBucket, $filePath, $bRecursive = false) { global $APPLICATION; $result = array( "dir" => array(), "file" => array(), "file_size" => array(), ); $filePath = trim($filePath, '/'); if(strlen($filePath)) $filePath .= '/'; if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = $arBucket["PREFIX"]."/".ltrim($filePath, "/"); } $filePath = $APPLICATION->ConvertCharset($filePath, LANG_CHARSET, "UTF-8"); $marker = ''; while(true) { $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'GET', $arBucket["BUCKET"], '/', '?'.($bRecursive? '': 'delimiter=/&').'prefix='.urlencode($filePath).'&marker='.urlencode($marker) ); if( $this->status == 200 && is_array($response) && isset($response["ListBucketResult"]) && is_array($response["ListBucketResult"]) && isset($response["ListBucketResult"]["#"]) && is_array($response["ListBucketResult"]["#"]) ) { if( isset($response["ListBucketResult"]["#"]["CommonPrefixes"]) && is_array($response["ListBucketResult"]["#"]["CommonPrefixes"]) ) { foreach($response["ListBucketResult"]["#"]["CommonPrefixes"] as $a) { $dir_name = substr(rtrim($a["#"]["Prefix"][0]["#"], "/"), strlen($filePath)); $result["dir"][] = $APPLICATION->ConvertCharset(urldecode($dir_name), "UTF-8", LANG_CHARSET); } } if( isset($response["ListBucketResult"]["#"]["Contents"]) && is_array($response["ListBucketResult"]["#"]["Contents"]) ) { foreach($response["ListBucketResult"]["#"]["Contents"] as $a) { $file_name = substr($a["#"]["Key"][0]["#"], strlen($filePath)); $result["file"][] = $APPLICATION->ConvertCharset(urldecode($file_name), "UTF-8", LANG_CHARSET); $result["file_size"][] = $a["#"]["Size"][0]["#"]; } } if( isset($response["ListBucketResult"]["#"]["IsTruncated"]) && is_array($response["ListBucketResult"]["#"]["IsTruncated"]) && $response["ListBucketResult"]["#"]["IsTruncated"][0]["#"] === "true" && strlen($response["ListBucketResult"]["#"]["NextMarker"][0]["#"]) > 0 ) { $marker = $response["ListBucketResult"]["#"]["NextMarker"][0]["#"]; continue; } else { break; } } else { $APPLICATION->ResetException(); return false; } } return $result; } protected function StartUpload($arBucket, $filePath, $ContentType) { $filePath = '/'.trim($filePath, '/'); if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"].$filePath; } $filePathU = CCloudUtil::URLEncode($filePath, "UTF-8"); $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'POST', $arBucket["BUCKET"], $filePathU, '', '', array( "x-goog-acl"=>"public-read", "x-goog-resumable"=>"start", "Content-Type"=>$ContentType, ) ); if( $this->status == 201 && is_array($this->headers) && isset($this->headers["Location"]) && preg_match("/upload_id=(.*)\$/", $this->headers["Location"], $match) ) { return array( "filePath" => $filePath, "filePos" => 0, "upload_id" => $match[1], ); } return false; } function InitiateMultipartUpload($arBucket, &$NS, $filePath, $fileSize, $ContentType) { $upload_info = $this->StartUpload($arBucket, $filePath, $ContentType); if ($upload_info) { $upload_info["fileSize"] = $fileSize; $upload_info["ContentType"] = $ContentType; $NS = $upload_info; return true; } else { return false; } } function GetMinUploadPartSize() { return 5*1024*1024; //5MB } private function UploadRange($filePathU, $arBucket, &$NS, $data, $pos) { $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'PUT', $arBucket["BUCKET"], $filePathU.'?upload_id='.urlencode($NS["upload_id"]), '', '', array( "Content-Range" => "bytes */".$NS["fileSize"], ) ); $data_len = CUtil::BinStrlen($data); $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'PUT', $arBucket["BUCKET"], $filePathU.'?upload_id='.urlencode($NS["upload_id"]), '', $data, array( "Content-Range" => "bytes ".$pos."-".($pos+$data_len-1)."/".$NS["fileSize"], ) ); } function UploadPartNo($arBucket, &$NS, $data, $part_no) { global $APPLICATION; $part_no = intval($part_no); $found = false; if (isset($NS["Parts"])) { foreach ($NS["Parts"] as $first_part_no => $part) { if ($part["part_no"] === ($part_no - 1)) { $found = $first_part_no; break; } } } else { $NS["Parts"] = array(); } if ($found === false) { $partFileName = '/'.trim($NS["filePath"], '/').".tmp".$part_no; if($arBucket["PREFIX"]) { if(substr($partFileName, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $partFileName = "/".$arBucket["PREFIX"].$partFileName; } $upload_info = $this->StartUpload($arBucket, $partFileName, $NS["ContentType"]); if ($upload_info) { $upload_info["fileSize"] = "*"; $upload_info["part_no"] = $part_no; $found = $part_no; $NS["Parts"][$part_no] = $upload_info; ksort($NS["Parts"]); } else { return false; } } $NS["Parts"][$found]["part_no"] = $part_no; if ( (isset($NS["Parts"][$part_no + 1])) || (($NS["Parts"][$found]["part_no"] * $this->GetMinUploadPartSize() + $this->GetMinUploadPartSize()) >= $NS["fileSize"]) ) { $data_len = CUtil::BinStrlen($data); $NS["Parts"][$found]["fileSize"] = $NS["Parts"][$found]["filePos"] + $data_len; } $filePath = $NS["Parts"][$found]["filePath"]; $filePathU = CCloudUtil::URLEncode($filePath, "UTF-8"); $this->UploadRange($filePathU, $arBucket, $NS["Parts"][$found], $data, $NS["Parts"][$found]["filePos"]); if( $this->status == 308 && is_array($this->headers) && preg_match("/^bytes=(\\d+)-(\\d+)\$/", $this->headers["Range"], $match) ) { $APPLICATION->ResetException(); $NS["Parts"][$found]["filePos"] = $match[2]+1; return true; } elseif($this->status == 200) { return true; } else { return false; } } function UploadPart($arBucket, &$NS, $data) { global $APPLICATION; $filePath = '/'.trim($NS["filePath"], '/'); if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"].$filePath; } $filePathU = CCloudUtil::URLEncode($filePath, "UTF-8"); $this->UploadRange($filePathU, $arBucket, $NS, $data, $NS["filePos"]); if( $this->status == 308 && is_array($this->headers) && preg_match("/^bytes=(\\d+)-(\\d+)\$/", $this->headers["Range"], $match) ) { $APPLICATION->ResetException(); $NS["filePos"] = $match[2]+1; return true; } elseif($this->status == 200) { return true; } else { return false; } } function CompleteMultipartUpload($arBucket, &$NS) { if (isset($NS["Parts"])) { // https://cloud.google.com/storage/docs/xml-api/put-object-compose $filePath = '/'.trim($NS["filePath"], '/'); if($arBucket["PREFIX"]) { if(substr($filePath, 0, strlen($arBucket["PREFIX"])+2) != "/".$arBucket["PREFIX"]."/") $filePath = "/".$arBucket["PREFIX"].$filePath; } $filePathU = CCloudUtil::URLEncode($filePath, "UTF-8"); $xml = "<ComposeRequest>"; foreach ($NS["Parts"] as $i => $part) { $xml .= "<Component><Name>".ltrim($part["filePath"], '/')."</Name></Component>"; } $xml .= "</ComposeRequest>"; $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'PUT', $arBucket["BUCKET"], $filePathU.'?compose', '', $xml, array( "x-goog-acl"=>"public-read", "Content-Type"=>$NS["ContentType"], ) ); if ($this->status == 200) { foreach ($NS["Parts"] as $i => $part) { $this->DeleteFile($arBucket, $part["filePath"]); } return true; } else { AddMessage2Log($this); return false; } } return true; } function SendRequest($access_key, $secret_key, $verb, $bucket, $file_name='/', $params='', $content='', $additional_headers=array()) { global $APPLICATION; $this->status = 0; if(isset($additional_headers["Content-Type"])) { $ContentType = $additional_headers["Content-Type"]; unset($additional_headers["Content-Type"]); } else { $ContentType = $content? 'text/plain': ''; } if(!array_key_exists("x-goog-api-version", $additional_headers)) $additional_headers["x-goog-api-version"] = "1"; $RequestMethod = $verb; $RequestURI = $file_name; $RequestDATE = gmdate('D, d M Y H:i:s', time()).' GMT'; //Prepare Signature $CanonicalizedAmzHeaders = ""; ksort($additional_headers); foreach($additional_headers as $key => $value) if(preg_match("/^x-goog-/", $key)) $CanonicalizedAmzHeaders .= $key.":".$value."\n"; $CanonicalizedResource = "/".$bucket.$RequestURI; $StringToSign = "$RequestMethod\n\n$ContentType\n$RequestDATE\n$CanonicalizedAmzHeaders$CanonicalizedResource"; //$utf = $APPLICATION->ConvertCharset($StringToSign, LANG_CHARSET, "UTF-8"); $Signature = base64_encode($this->hmacsha1($StringToSign, $secret_key)); $Authorization = "GOOG1 ".$access_key.":".$Signature; $obRequest = new CHTTP; $obRequest->additional_headers["Date"] = $RequestDATE; $obRequest->additional_headers["Authorization"] = $Authorization; foreach($additional_headers as $key => $value) if(!preg_match("/^option-/", $key)) $obRequest->additional_headers[$key] = $value; if( $this->new_end_point && preg_match('#^(http|https)://'.preg_quote($bucket, '#').'(.+)/#', $this->new_end_point, $match)) { $host = $match[2]; } else { $host = $bucket.".commondatastorage.googleapis.com"; } $was_end_point = $this->new_end_point; $this->new_end_point = ''; $obRequest->Query( $this->verb = $RequestMethod, $host, 80, $this->url = $RequestURI.$params, $content, '', $ContentType ); $this->headers_sent = $obRequest->additional_headers; $this->status = $obRequest->status; $this->headers = $obRequest->headers; $this->errno = $obRequest->errno; $this->errstr = $obRequest->errstr; $this->result = $obRequest->result; if($obRequest->status == 200) { if(isset($additional_headers["option-raw-result"])) { return $obRequest->result; } elseif($obRequest->result) { $obXML = new CDataXML; $text = preg_replace("/<"."\\?XML.*?\\?".">/i", "", $obRequest->result); if($obXML->LoadString($text)) { $arXML = $obXML->GetArray(); if(is_array($arXML)) { return $arXML; } } //XML parse error $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_PARSE_ERROR', array('#errno#'=>1))); return false; } else { //Empty success result return array(); } } elseif( $obRequest->status == 307 //Temporary redirect && isset($obRequest->headers["Location"]) && !$was_end_point //No recurse yet ) { $this->new_end_point = $obRequest->headers["Location"]; return $this->SendRequest( $access_key, $secret_key, $verb, $bucket, $file_name, $params, $content, $additional_headers ); } elseif($obRequest->status > 0) { if($obRequest->result) { $obXML = new CDataXML; if($obXML->LoadString($obRequest->result)) { $arXML = $obXML->GetArray(); if(is_array($arXML) && is_string($arXML["Error"]["#"]["Message"][0]["#"])) { $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_ERROR', array('#errmsg#'=>trim($arXML["Error"]["#"]["Message"][0]["#"], '.')))); return false; } } } $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_PARSE_ERROR', array('#errno#'=>2))); return false; } else { $APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_PARSE_ERROR', array('#errno#'=>3))); return false; } } function hmacsha1($data, $key) { if(strlen($key)>64) $key=pack('H*', sha1($key)); $key = str_pad($key, 64, chr(0x00)); $ipad = str_repeat(chr(0x36), 64); $opad = str_repeat(chr(0x5c), 64); $hmac = pack('H*', sha1(($key^$opad).pack('H*', sha1(($key^$ipad).$data)))); return $hmac; } } ?>classes/general/storage_service_hotbox.php000064400000010341150241560060015074 0ustar00<? IncludeModuleLangFile(__FILE__); class CCloudStorageService_HotBox extends CCloudStorageService_AmazonS3 { protected $status = 0; protected $verb = ''; protected $host = ''; protected $url = ''; protected $headers =/*.(array[string]string).*/array(); protected $set_headers =/*.(array[string]string).*/array(); protected $errno = 0; protected $errstr = ''; protected $result = ''; protected $new_end_point = ''; protected $_public = true; protected $location = ''; /** * @return int */ function GetLastRequestStatus() { return $this->status; } /** * @return CCloudStorageService */ function GetObject() { return new CCloudStorageService_HotBox(); } /** * @return string */ function GetID() { return "hot_box"; } /** * @return string */ function GetName() { return "HotBox"; } /** * @return array[string]string */ function GetLocationList() { return array( "" => "hb.bizmrg.com", ); } /** * @param array[string]string $arBucket * @param bool $bServiceSet * @param string $cur_SERVICE_ID * @param bool $bVarsFromForm * @return string */ function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm) { if($bVarsFromForm) $arSettings = $_POST["SETTINGS"][$this->GetID()]; else $arSettings = unserialize($arBucket["SETTINGS"]); if(!is_array($arSettings)) $arSettings = array("ACCESS_KEY" => "", "SECRET_KEY" => ""); $htmlID = htmlspecialcharsbx($this->GetID()); $result = ' <tr id="SETTINGS_0_'.$htmlID.'" style="display:'.($cur_SERVICE_ID === $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_S3_EDIT_ACCESS_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][ACCESS_KEY]" id="'.$htmlID.'ACCESS_KEY" value="'.htmlspecialcharsbx($arSettings['ACCESS_KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_ACCESS_KEY" id="'.$htmlID.'INP_ACCESS_KEY" value="'.htmlspecialcharsbx($arSettings['ACCESS_KEY']).'" '.($arBucket['READ_ONLY'] === 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'ACCESS_KEY\').value = this.value"></td> </tr> <tr id="SETTINGS_1_'.$htmlID.'" style="display:'.($cur_SERVICE_ID === $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_S3_EDIT_SECRET_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][SECRET_KEY]" id="'.$htmlID.'SECRET_KEY" value="'.htmlspecialcharsbx($arSettings['SECRET_KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_SECRET_KEY" id="'.$htmlID.'INP_SECRET_KEY" value="'.htmlspecialcharsbx($arSettings['SECRET_KEY']).'" autocomplete="off" '.($arBucket['READ_ONLY'] === 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'SECRET_KEY\').value = this.value"></td> </tr> '; return $result; } protected function GetRequestHost($bucket) { if( $this->new_end_point != "" && preg_match('#^(http|https)://'.preg_quote($bucket, '#').'(.+?)/#', $this->new_end_point, $match) > 0 ) { return $bucket.$match[2]; } else { return $bucket.".hb.bizmrg.com"; } } /** * @param array[string]string $arBucket * @param mixed $arFile * @return string */ function GetFileSRC($arBucket, $arFile) { $proto = CMain::IsHTTPS()? "https": "http"; if($arBucket["CNAME"] != "") { $host = $arBucket["CNAME"]; $pref = ""; } elseif ($proto === "https" && strpos($arBucket["BUCKET"], ".") !== false) { $host = "hb.bizmrg.com"; $pref = $arBucket["BUCKET"]; } else { $host = $arBucket["BUCKET"].".hb.bizmrg.com"; $pref = ""; } if(is_array($arFile)) $URI = ltrim($arFile["SUBDIR"]."/".$arFile["FILE_NAME"], "/"); else $URI = ltrim($arFile, "/"); if ($arBucket["PREFIX"] != "") { if(substr($URI, 0, strlen($arBucket["PREFIX"])+1) !== $arBucket["PREFIX"]."/") $URI = $arBucket["PREFIX"]."/".$URI; } if ($pref !== "") { $URI = $pref."/".$URI; } return $proto."://$host/".CCloudUtil::URLEncode($URI, "UTF-8"); } /** * @param array[string]string $arBucket * @return bool */ function DeleteBucket($arBucket) { //Do not delete bucket if there is some files left if(!$this->IsEmptyBucket($arBucket)) return false; return parent::DeleteBucket($arBucket); } } classes/general/storage_service.php000064400000010473150241560060013517 0ustar00<? abstract class CCloudStorageService { public $tokenHasExpired = false; /** * @return CCloudStorageService * @deprecated */ abstract public function GetObject(); /** * @return CCloudStorageService */ public static function GetObjectInstance() { return new static(); } /** * @return string */ abstract public function GetID(); /** * @return string */ abstract public function GetName(); /** * @return array[string]string */ abstract public function GetLocationList(); /** * @param array[string]string $arBucket * @param bool $bServiceSet * @param string $cur_SERVICE_ID * @param bool $bVarsFromForm * @return string */ abstract public function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm); /** * @param array[string]string $arBucket * @param array[string]string $arSettings * @return bool */ abstract public function CheckSettings($arBucket, &$arSettings); /** * @param array[string]string $arBucket * @return bool */ abstract public function CreateBucket($arBucket); /** * @param array[string]string $arBucket * @return bool */ abstract public function DeleteBucket($arBucket); /** * @param array[string]string $arBucket * @return bool */ abstract public function IsEmptyBucket($arBucket); /** * @param array[string]string $arBucket * @param mixed $arFile * @return string */ abstract public function GetFileSRC($arBucket, $arFile); /** * @param array[string]string $arBucket * @param string $filePath * @return bool */ abstract public function FileExists($arBucket, $filePath); /** * @param array[string]string $arBucket * @param mixed $arFile * @param string $filePath * @return bool */ abstract public function FileCopy($arBucket, $arFile, $filePath); /** * @param array[string]string $arBucket * @param string $sourcePath * @param string $targetPath * @param bool $overwrite * @return bool */ public function FileRename($arBucket, $sourcePath, $targetPath, $overwrite = true) { if ($this->FileExists($arBucket, $sourcePath)) { $contentType = $this->headers["Content-Type"]; } else { return false; } if ($this->FileExists($arBucket, $targetPath)) { if (!$overwrite) { return false; } if (!$this->DeleteFile($arBucket, $targetPath)) { return false; } } $arFile = array( "SUBDIR" => 0, "FILE_NAME" => ltrim($sourcePath, "/"), "CONTENT_TYPE" => $contentType, ); if (!$this->FileCopy($arBucket, $arFile, $targetPath)) { return false; } if (!$this->DeleteFile($arBucket, $sourcePath)) { return false; } return true; } /** * @param array[string]string $arBucket * @param mixed $arFile * @param string $filePath * @return bool */ abstract public function DownloadToFile($arBucket, $arFile, $filePath); /** * @param array[string]string $arBucket * @param string $filePath * @return bool */ abstract public function DeleteFile($arBucket, $filePath); /** * @param array[string]string $arBucket * @param string $filePath * @param mixed $arFile * @return bool */ abstract public function SaveFile($arBucket, $filePath, $arFile); /** * @param array[string]string $arBucket * @param string $filePath * @param bool $bRecursive * @return array[string][int]string */ abstract public function ListFiles($arBucket, $filePath, $bRecursive = false); /** * @param array[string]string $arBucket * @param mixed $NS * @param string $filePath * @param float $fileSize * @param string $ContentType * @return bool */ abstract public function InitiateMultipartUpload($arBucket, &$NS, $filePath, $fileSize, $ContentType); /** * @return float */ abstract public function GetMinUploadPartSize(); /** * @param array[string]string $arBucket * @param mixed $NS * @param string $data * @return bool */ abstract public function UploadPart($arBucket, &$NS, $data); /** * @param array[string]string $arBucket * @param mixed $NS * @return bool */ abstract public function CompleteMultipartUpload($arBucket, &$NS); /** * @param string $name * @param string $value * @return void */ public function SetHeader($name, $value) { } /** * @param string $name * @return void */ public function UnsetHeader($name) { } /** * @param bool $public * @return void */ public function SetPublic($public) { } } ?>classes/general/storage_service_selectel.php000064400000005322150241560060015374 0ustar00<? IncludeModuleLangFile(__FILE__); class CCloudStorageService_Selectel extends CCloudStorageService_OpenStackStorage { function GetObject() { return new CCloudStorageService_Selectel(); } function GetID() { return "selectel_storage"; } function GetName() { return "Selectel"; } function GetSettingsHTML($arBucket, $bServiceSet, $cur_SERVICE_ID, $bVarsFromForm) { if($bVarsFromForm) $arSettings = $_POST["SETTINGS"][$this->GetID()]; else $arSettings = unserialize($arBucket["SETTINGS"]); if(!is_array($arSettings)) $arSettings = array("HOST" => "auth.selcdn.ru", "USER" => "", "KEY" => ""); $htmlID = htmlspecialcharsbx($this->GetID()); $result = ' <tr id="SETTINGS_2_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_SELECTEL_EDIT_HOST").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][HOST]" id="'.$htmlID.'HOST" value="'.htmlspecialcharsbx($arSettings['HOST']).'"><input type="text" size="55" name="'.$htmlID.'INP_HOST" id="'.$htmlID.'INP_HOST" value="'.htmlspecialcharsbx($arSettings['HOST']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'HOST\').value = this.value"></td> </tr> <tr id="SETTINGS_0_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_SELECTEL_EDIT_USER").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][USER]" id="'.$htmlID.'USER" value="'.htmlspecialcharsbx($arSettings['USER']).'"><input type="text" size="55" name="'.$htmlID.'INP_" id="'.$htmlID.'INP_USER" value="'.htmlspecialcharsbx($arSettings['USER']).'" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'USER\').value = this.value"></td> </tr> <tr id="SETTINGS_1_'.$htmlID.'" style="display:'.($cur_SERVICE_ID == $this->GetID() || !$bServiceSet? '': 'none').'" class="settings-tr adm-detail-required-field"> <td>'.GetMessage("CLO_STORAGE_SELECTEL_EDIT_KEY").':</td> <td><input type="hidden" name="SETTINGS['.$htmlID.'][KEY]" id="'.$htmlID.'KEY" value="'.htmlspecialcharsbx($arSettings['KEY']).'"><input type="text" size="55" name="'.$htmlID.'INP_KEY" id="'.$htmlID.'INP_KEY" value="'.htmlspecialcharsbx($arSettings['KEY']).'" autocomplete="off" '.($arBucket['READ_ONLY'] == 'Y'? '"disabled"': '').' onchange="BX(\''.$htmlID.'KEY\').value = this.value"></td> </tr> '; return $result; } function CheckSettings($arBucket, &$arSettings) { if(is_array($arSettings)) $arSettings["HOST"] = "auth.selcdn.ru"; return parent::CheckSettings($arBucket, $arSettings); } } ?>classes/general/storage.php000064400000113027150241560060011776 0ustar00<?php IncludeModuleLangFile(__FILE__); class CCloudStorage { const FILE_SKIPPED = 0; const FILE_MOVED = 1; const FILE_PARTLY_UPLOADED = 2; const FILE_UPLOAD_ERROR = 3; public static $part_size = 0; public static $part_count = 0; private static $_services = /*.(array[string]CCloudStorageService).*/ null; /** * @return void */ static function _init() { if (!isset(self::$_services)) { $obService = /*.(CCloudStorageService).*/ null; self::$_services = /*.(array[string]CCloudStorageService).*/ array(); foreach (GetModuleEvents("clouds", "OnGetStorageService", true) as $arEvent) { $obService = ExecuteModuleEventEx($arEvent); if (is_object($obService)) self::$_services[$obService->GetID()] = $obService; } } } /** * @param string $ID * @return CCloudStorageService */ public static function GetServiceByID($ID) { self::_init(); if (array_key_exists($ID, self::$_services)) return self::$_services[$ID]; else return null; } /** * @return array[string]CCloudStorageService */ public static function GetServiceList() { self::_init(); return self::$_services; } /** * @param string $ID * @return array[string]string */ public static function GetServiceLocationList($ID) { $obService = CCloudStorage::GetServiceByID($ID); if (is_object($obService)) return $obService->GetLocationList(); else return /*.(array[string]string).*/ array(); } /** * @param string $ID * @return string */ public static function GetServiceDescription($ID) { $obService = CCloudStorage::GetServiceByID($ID); if (is_object($obService)) return $obService->GetName(); else return ""; } /** * @param array [string]string $arFile * @param string $strFileName * @return CCloudStorageBucket */ public static function FindBucketForFile($arFile, $strFileName) { if (array_key_exists("size", $arFile)) $file_size = intval($arFile["size"]); else $file_size = intval($arFile["FILE_SIZE"]); foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { if ($bucket["ACTIVE"] === "Y" && $bucket["READ_ONLY"] !== "Y") { foreach ($bucket["FILE_RULES_COMPILED"] as $rule) { if ($rule["MODULE_MASK"] != "") { $bMatchModule = (preg_match($rule["MODULE_MASK"], $arFile["MODULE_ID"]) > 0); } else { $bMatchModule = true; } if ($rule["EXTENTION_MASK"] != "") { $bMatchExtention = (preg_match($rule["EXTENTION_MASK"], $strFileName) > 0) || (preg_match($rule["EXTENTION_MASK"], $arFile["ORIGINAL_NAME"]) > 0); } else { $bMatchExtention = true; } if ($rule["SIZE_ARRAY"]) { $bMatchSize = false; foreach ($rule["SIZE_ARRAY"] as $size) { if ( ($file_size >= $size[0]) && ($size[1] === 0.0 || $file_size <= $size[1]) ) $bMatchSize = true; } } else { $bMatchSize = true; } if ($bMatchModule && $bMatchExtention && $bMatchSize) { return new CCloudStorageBucket(intval($bucket["ID"])); } } } } return null; } /** * @param array [string]string $arFile * @param array [string]string $arResizeParams * @param array [string]mixed $callbackData * @param bool $bNeedResize * @param array [string]string $sourceImageFile * @param array [string]string $cacheImageFileTmp * @return bool */ public static function OnBeforeResizeImage($arFile, $arResizeParams, &$callbackData, &$bNeedResize, &$sourceImageFile, &$cacheImageFileTmp) { $callbackData = null; if (intval($arFile["HANDLER_ID"]) <= 0) return false; $obSourceBucket = new CCloudStorageBucket(intval($arFile["HANDLER_ID"])); if (!$obSourceBucket->Init()) return false; $callbackData = /*.(array[string]mixed).*/ array(); $callbackData["obSourceBucket"] = $obSourceBucket; //Assume target bucket same as source $callbackData["obTargetBucket"] = $obTargetBucket = $obSourceBucket; //if original file bucket is read only if ($obSourceBucket->READ_ONLY === "Y") //Try to find bucket with write rights { $bucket = CCloudStorage::FindBucketForFile($arFile, $arFile["FILE_NAME"]); if (!is_object($bucket)) return false; if ($bucket->Init()) { $callbackData["obTargetBucket"] = $obTargetBucket = $bucket; } } if (defined("BX_MOBILE") && constant("BX_MOBILE") === true) $bImmediate = true; else $bImmediate = $arResizeParams[5]; $callbackData["cacheID"] = $arFile["ID"]."/".md5(serialize($arResizeParams)); $callbackData["cacheOBJ"] = new CPHPCache; $callbackData["fileDIR"] = "/"."resize_cache/".$callbackData["cacheID"]."/".$arFile["SUBDIR"]; $callbackData["fileNAME"] = $arFile["FILE_NAME"]; $callbackData["fileURL"] = $callbackData["fileDIR"]."/".$callbackData["fileNAME"]; $result = true; if ($callbackData["cacheOBJ"]->StartDataCache(CACHED_clouds_file_resize, $callbackData["cacheID"], "clouds")) { $cacheImageFile = $callbackData["obTargetBucket"]->GetFileSRC($callbackData["fileURL"]); $arDestinationSize = array(); //Check if it is cache file was deleted, but there was a successful resize if ( !$bImmediate && COption::GetOptionString("clouds", "delayed_resize") === "Y" && is_array($delayInfo = CCloudStorage::ResizeImageFileGet($cacheImageFile)) && $delayInfo["ERROR_CODE"] < 10 ) { $callbackData["cacheSTARTED"] = true; if ($arFile["FILE_SIZE"] > 1) $callbackData["fileSize"] = $arFile["FILE_SIZE"]; $bNeedResize = false; $result = true; } elseif ( is_array($delayInfo = CCloudStorage::ResizeImageFileGet($cacheImageFile)) && $delayInfo["ERROR_CODE"] < 10 ) { $callbackData["cacheSTARTED"] = true; if ($arFile["FILE_SIZE"] > 1) $callbackData["fileSize"] = $arFile["FILE_SIZE"]; $bNeedResize = false; $result = true; } //Check if it is cache file was deleted, but not the file in the cloud elseif ($fs = $obTargetBucket->FileExists($callbackData["fileURL"])) { //If file was resized before the fact was registered if (COption::GetOptionString("clouds", "delayed_resize") === "Y") { CCloudStorage::ResizeImageFileAdd( $arDestinationSize, $arFile, $cacheImageFile, $arResizeParams, 9 //already where ); } $callbackData["cacheSTARTED"] = true; if ($fs > 1) $callbackData["fileSize"] = $fs; $bNeedResize = false; $result = true; } else { $callbackData["tmpFile"] = CFile::GetTempName('', $arFile["FILE_NAME"]); $callbackData["tmpFile"] = preg_replace("#[\\\\\\/]+#", "/", $callbackData["tmpFile"]); if ( !$bImmediate && COption::GetOptionString("clouds", "delayed_resize") === "Y" && CCloudStorage::ResizeImageFileDelay( $arDestinationSize, $arFile, $cacheImageFile, $arResizeParams ) ) { $callbackData["cacheSTARTED"] = false; $bNeedResize = false; $callbackData["cacheOBJ"]->AbortDataCache(); $callbackData["cacheVARS"] = array( "cacheImageFile" => $cacheImageFile, "width" => $arDestinationSize["width"], "height" => $arDestinationSize["height"], ); $result = true; } elseif ($obSourceBucket->DownloadToFile($arFile, $callbackData["tmpFile"])) { $callbackData["cacheSTARTED"] = true; $bNeedResize = true; $sourceImageFile = $callbackData["tmpFile"]; $cacheImageFileTmp = CFile::GetTempName('', $arFile["FILE_NAME"]); $result = true; } else { $callbackData["cacheSTARTED"] = false; $bNeedResize = false; $callbackData["cacheOBJ"]->AbortDataCache(); $result = false; } } } else { $callbackData["cacheSTARTED"] = false; $callbackData["cacheVARS"] = $callbackData["cacheOBJ"]->GetVars(); $bNeedResize = false; $result = true; } return $result; } public static function OnAfterResizeImage($arFile, $arResizeParams, &$callbackData, &$cacheImageFile, &$cacheImageFileTmp, &$arImageSize) { global $arCloudImageSizeCache; $io = CBXVirtualIo::GetInstance(); if (!is_array($callbackData)) return false; if ($callbackData["cacheSTARTED"]) { /** @var CCloudStorageBucket $obTargetBucket */ $obTargetBucket = $callbackData["obTargetBucket"]; /** @var CPHPCache $cacheOBJ */ $cacheOBJ = $callbackData["cacheOBJ"]; if (isset($callbackData["tmpFile"])) //have to upload to the cloud { $arFileToStore = CFile::MakeFileArray($io->GetPhysicalName($cacheImageFileTmp)); if (!preg_match("/^image\\//", $arFileToStore["type"])) $arFileToStore["type"] = $arFile["CONTENT_TYPE"]; if ($obTargetBucket->SaveFile($callbackData["fileURL"], $arFileToStore)) { $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData["fileURL"]); $arImageSize = CFile::GetImageSize($cacheImageFileTmp); $arImageSize[2] = filesize($io->GetPhysicalName($cacheImageFileTmp)); $iFileSize = filesize($arFileToStore["tmp_name"]); if (!is_array($arImageSize)) $arImageSize = array(0, 0); $cacheOBJ->EndDataCache(array( "cacheImageFile" => $cacheImageFile, "width" => $arImageSize[0], "height" => $arImageSize[1], "size" => $arImageSize[2], )); $tmpFile = $io->GetPhysicalName($callbackData["tmpFile"]); unlink($tmpFile); @rmdir(substr($tmpFile, 0, -strlen(bx_basename($tmpFile)))); $arCloudImageSizeCache[$cacheImageFile] = $arImageSize; $obTargetBucket->IncFileCounter($iFileSize); if ( COption::GetOptionString("clouds", "delayed_resize") === "Y" && !is_array(CCloudStorage::ResizeImageFileGet($cacheImageFile)) ) { $arDestinationSize = array(); CCloudStorage::ResizeImageFileAdd( $arDestinationSize, $arFile, $cacheImageFile, $arResizeParams, 9 //already there ); } return true; } else { $cacheOBJ->AbortDataCache(); $tmpFile = $io->GetPhysicalName($callbackData["tmpFile"]); unlink($tmpFile); @rmdir(substr($tmpFile, 0, -strlen(bx_basename($tmpFile)))); unlink($cacheImageFileTmp); @rmdir(substr($cacheImageFileTmp, 0, -strlen(bx_basename($cacheImageFileTmp)))); // $cacheImageFile not clear what to do return false; } } else //the file is already in the cloud { $bNeedCreatePicture = false; $arSourceSize = array("x" => 0, "y" => 0, "width" => 0, "height" => 0); $arDestinationSize = array("x" => 0, "y" => 0, "width" => 0, "height" => 0); CFile::ScaleImage($arFile["WIDTH"], $arFile["HEIGHT"], $arResizeParams[0], $arResizeParams[1], $bNeedCreatePicture, $arSourceSize, $arDestinationSize); $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData["fileURL"]); $arImageSize = array( $arDestinationSize["width"], $arDestinationSize["height"], isset($callbackData["fileSize"])? $callbackData["fileSize"]: $obTargetBucket->GetFileSize($callbackData["fileURL"]), ); $cacheOBJ->EndDataCache(array( "cacheImageFile" => $cacheImageFile, "width" => $arImageSize[0], "height" => $arImageSize[1], "size" => $arImageSize[2], )); $arCloudImageSizeCache[$cacheImageFile] = $arImageSize; return true; } } elseif (is_array($callbackData["cacheVARS"])) { $cacheImageFile = $callbackData["cacheVARS"]["cacheImageFile"]; $arImageSize = array( $callbackData["cacheVARS"]["width"], $callbackData["cacheVARS"]["height"], $callbackData["cacheVARS"]["size"], ); $arCloudImageSizeCache[$cacheImageFile] = $arImageSize; return true; } return false; } public static function ResizeImageFileGet($destinationFile) { global $DB; $destinationFile = preg_replace("/^https?:/i", "", $destinationFile); $q = $DB->Query(" select ID ,ERROR_CODE ,FILE_ID ,".$DB->DateToCharFunction("TIMESTAMP_X", "FULL")." TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '".$DB->ForSql($destinationFile)."' "); $a = $q->Fetch(); return $a; } public static function ResizeImageFileAdd(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams, $errorCode = 0) { global $DB; $destinationFile = preg_replace("/^https?:/i", "", $destinationFile); $q = $DB->Query(" select ID ,ERROR_CODE ,PARAMS ,".$DB->DateToCharFunction("TIMESTAMP_X", "FULL")." TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '".$DB->ForSql($destinationFile)."' "); $a = $q->Fetch(); if ($a && $a["ERROR_CODE"] >= 10 && $a["ERROR_CODE"] < 20) { $DB->Query("DELETE from b_clouds_file_resize WHERE ID = ".$a["ID"]); $a = false; } if (!$a) { $arResizeParams["type"] = $sourceFile["CONTENT_TYPE"]; $DB->Add("b_clouds_file_resize", array( "~TIMESTAMP_X" => $DB->CurrentTimeFunction(), "ERROR_CODE" => intval($errorCode), "PARAMS" => serialize($arResizeParams), "FROM_PATH" => $sourceFile["SRC"], "TO_PATH" => $destinationFile, "FILE_ID" => $sourceFile["ID"], )); } } public static function ResizeImageFileDelay(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams) { global $DB; $destinationFile = preg_replace("/^https?:/i", "", $destinationFile); $q = $DB->Query(" select ID ,ERROR_CODE ,PARAMS ,".$DB->DateToCharFunction("TIMESTAMP_X", "FULL")." TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '".$DB->ForSql($destinationFile)."' "); if ($resize = $q->Fetch()) { if ($resize["ERROR_CODE"] < 10) { $arResizeParams = unserialize($resize["PARAMS"]); $id = $resize["ID"]; } //Give it a try elseif ( $resize["ERROR_CODE"] >= 10 && $resize["ERROR_CODE"] < 20 && (MakeTimeStamp($resize["TIMESTAMP_X"]) + 300/*5min*/) < (time() + CTimeZone::GetOffset()) ) { $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE='1' WHERE ID=".$resize["ID"]." "); $arResizeParams = unserialize($resize["PARAMS"]); $id = $resize["ID"]; } else { return false; } } else { $id = 0; } $sourceImageWidth = $sourceFile["WIDTH"]; $sourceImageHeight = $sourceFile["HEIGHT"]; $arSize = $arResizeParams[0]; $resizeType = $arResizeParams[1]; $arWaterMark = $arResizeParams[2]; $jpgQuality = $arResizeParams[3]; $arFilters = $arResizeParams[4]; $bNeedCreatePicture = false; $arSourceSize = array("x" => 0, "y" => 0, "width" => 0, "height" => 0); $arDestinationSize = array("x" => 0, "y" => 0, "width" => 0, "height" => 0); CFile::ScaleImage( $sourceImageWidth, $sourceImageHeight, $arSize, $resizeType, $bNeedCreatePicture, $arSourceSize, $arDestinationSize ); $bNeedCreatePicture |= is_array($arWaterMark) && !empty($arWaterMark); $bNeedCreatePicture |= is_array($arFilters) && !empty($arFilters); if ($bNeedCreatePicture) { if ($id <= 0) { $arResizeParams["type"] = $sourceFile["CONTENT_TYPE"]; $id = $DB->Add("b_clouds_file_resize", array( "~TIMESTAMP_X" => $DB->CurrentTimeFunction(), "ERROR_CODE" => "2", "PARAMS" => serialize($arResizeParams), "FROM_PATH" => $sourceFile["SRC"], "TO_PATH" => $destinationFile, "FILE_ID" => $sourceFile["ID"], )); } return $id > 0; } else { return false; } } /** * @param CCloudStorageBucket $obBucket * @param string $path * @return bool */ public static function ResizeImageFileCheck($obBucket, $path) { global $DB; $path = preg_replace("/^https?:/i", "", $path); $q = $DB->Query(" select ID ,ERROR_CODE ,TO_PATH ,FROM_PATH ,PARAMS ,".$DB->DateToCharFunction("TIMESTAMP_X", "FULL")." TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '".$DB->ForSql($path)."' "); $task = $q->Fetch(); if (!$task) return false; //File in the Sky with Diamonds if ($task["ERROR_CODE"] == 9) { return true; } //Fatal error if ($task["ERROR_CODE"] >= 20) { return false; } //Recoverable error if ($task["ERROR_CODE"] >= 10 && $task["ERROR_CODE"] < 20) { if ((MakeTimeStamp($task["TIMESTAMP_X"]) + 300/*5min*/) > (time() + CTimeZone::GetOffset())) return false; } $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '11' WHERE ID = ".$task["ID"]." "); $tmpFile = CFile::MakeFileArray($task["FROM_PATH"]); if (!is_array($tmpFile) || !file_exists($tmpFile["tmp_name"])) { $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '22' WHERE ID = ".$task["ID"]." "); return false; } $arResizeParams = unserialize($task["PARAMS"]); if (!is_array($arResizeParams)) { $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '23' WHERE ID = ".$task["ID"]." "); return false; } $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '14' WHERE ID = ".$task["ID"]." "); $arSize = $arResizeParams[0]; $resizeType = $arResizeParams[1]; $arWaterMark = $arResizeParams[2]; $jpgQuality = $arResizeParams[3]; $arFilters = $arResizeParams[4]; $to_path = CFile::GetTempName('', bx_basename($task["TO_PATH"])); if (!CFile::ResizeImageFile($tmpFile["tmp_name"], $to_path, $arSize, $resizeType, $arWaterMark, $jpgQuality, $arFilters)) { $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '25' WHERE ID = ".$task["ID"]." "); return false; } $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '16' WHERE ID = ".$task["ID"]." "); $fileToStore = CFile::MakeFileArray($to_path); if ($arResizeParams["type"] && !preg_match("/^image\\//", $fileToStore["type"])) $fileToStore["type"] = $arResizeParams["type"]; $baseURL = preg_replace("/^https?:/i", "", $obBucket->GetFileSRC("/")); $pathToStore = substr($task["TO_PATH"], strlen($baseURL) - 1); if (!$obBucket->SaveFile(urldecode($pathToStore), $fileToStore)) { $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '27' WHERE ID = ".$task["ID"]." "); return false; } $obBucket->IncFileCounter($fileToStore["size"]); $DB->Query(" UPDATE b_clouds_file_resize SET ERROR_CODE = '9' WHERE ID = ".$task["ID"]." "); return true; } public static function OnMakeFileArray($arSourceFile, &$arDestination) { if (!is_array($arSourceFile)) { $file = $arSourceFile; if (substr($file, 0, strlen($_SERVER["DOCUMENT_ROOT"])) == $_SERVER["DOCUMENT_ROOT"]) $file = ltrim(substr($file, strlen($_SERVER["DOCUMENT_ROOT"])), "/"); if (!preg_match("/^http:\\/\\//", $file)) return false; $bucket = CCloudStorage::FindBucketByFile($file); if (!is_object($bucket)) return false; $filePath = substr($file, strlen($bucket->GetFileSRC("/")) - 1); $filePath = urldecode($filePath); $target = CFile::GetTempName('', bx_basename($filePath)); $target = preg_replace("#[\\\\\\/]+#", "/", $target); if ($bucket->DownloadToFile($filePath, $target)) { $arDestination = $target; } return true; } else { if ($arSourceFile["HANDLER_ID"] <= 0) return false; $bucket = new CCloudStorageBucket($arSourceFile["HANDLER_ID"]); if (!$bucket->Init()) return false; $target = CFile::GetTempName('', $arSourceFile["FILE_NAME"]); $target = preg_replace("#[\\\\\\/]+#", "/", $target); if ($bucket->DownloadToFile($arSourceFile, $target)) { $arDestination["name"] = (strlen($arSourceFile['ORIGINAL_NAME']) > 0? $arSourceFile['ORIGINAL_NAME']: $arSourceFile['FILE_NAME']); $arDestination["size"] = $arSourceFile['FILE_SIZE']; $arDestination["type"] = $arSourceFile['CONTENT_TYPE']; $arDestination["description"] = $arSourceFile['DESCRIPTION']; $arDestination["tmp_name"] = $target; } return true; } } public static function OnFileDelete($arFile) { global $DB; if ($arFile["HANDLER_ID"] <= 0) return false; $bucket = new CCloudStorageBucket($arFile["HANDLER_ID"]); if ((!$bucket->Init()) || ($bucket->READ_ONLY === "Y")) return false; $result = $bucket->DeleteFile("/".$arFile["SUBDIR"]."/".$arFile["FILE_NAME"]); if ($result) $bucket->DecFileCounter($arFile["FILE_SIZE"]); $path = '/resize_cache/'.$arFile["ID"]."/"; $arCloudFiles = $bucket->ListFiles($path, true); if (is_array($arCloudFiles["file"])) { $delete_size = 0; foreach ($arCloudFiles["file"] as $i => $file_name) { $tmp = $bucket->DeleteFile($path.$file_name); if ($tmp) { $bucket->DecFileCounter($arCloudFiles["file_size"][$i]); $delete_size += $arCloudFiles["file_size"][$i]; } } /****************************** QUOTA ******************************/ if($delete_size > 0 && COption::GetOptionInt("main", "disk_space") > 0) CDiskQuota::updateDiskQuota("file", $delete_size, "delete"); /****************************** QUOTA ******************************/ } $DB->Query(" DELETE FROM b_clouds_file_resize WHERE FILE_ID = ".intval($arFile["ID"])." ", true); return $result; } public static function DeleteDirFilesEx($path) { $path = rtrim($path, "/")."/"; foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { $obBucket = new CCloudStorageBucket($bucket["ID"]); if ($obBucket->Init()) { $arCloudFiles = $obBucket->ListFiles($path, true); if (is_array($arCloudFiles["file"])) { foreach ($arCloudFiles["file"] as $i => $file_name) { $tmp = $obBucket->DeleteFile($path.$file_name); if ($tmp) $obBucket->DecFileCounter($arCloudFiles["file_size"][$i]); } } } } } public static function OnFileCopy(&$arFile, $newPath = "") { if ($arFile["HANDLER_ID"] <= 0) return false; $bucket = new CCloudStorageBucket($arFile["HANDLER_ID"]); if (!$bucket->Init()) return false; if ($bucket->READ_ONLY == "Y") return false; $filePath = ""; $newName = ""; if (strlen($newPath)) { $filePath = "/".trim(str_replace("//", "/", $newPath), "/"); } else { $strFileExt = strrchr($arFile["FILE_NAME"], "."); while (true) { $newName = md5(uniqid(mt_rand(), true)).$strFileExt; $filePath = "/".$arFile["SUBDIR"]."/".$newName; if (!$bucket->FileExists($filePath)) break; } } $result = $bucket->FileCopy($arFile, $filePath); if ($result) { $bucket->IncFileCounter($arFile["FILE_SIZE"]); if (strlen($newPath)) { $arFile["FILE_NAME"] = bx_basename($filePath); $arFile["SUBDIR"] = substr($filePath, 1, -(strlen(bx_basename($filePath)) + 1)); } else { $arFile["FILE_NAME"] = $newName; } } return $result; } public static function OnGetFileSRC($arFile) { if ($arFile["HANDLER_ID"] <= 0) return false; $bucket = new CCloudStorageBucket($arFile["HANDLER_ID"]); if ($bucket->Init()) return $bucket->GetFileSRC($arFile); else return false; } public static function MoveFile($arFile, $obTargetBucket) { $io = CBXVirtualIo::GetInstance(); //Try to find suitable bucket for the file $bucket = CCloudStorage::FindBucketForFile($arFile, $arFile["FILE_NAME"]); if (!is_object($bucket)) return CCloudStorage::FILE_SKIPPED; if (!$bucket->Init()) return CCloudStorage::FILE_SKIPPED; //Check if this is same bucket as the target if ($bucket->ID != $obTargetBucket->ID) return CCloudStorage::FILE_SKIPPED; if ($bucket->FileExists($bucket->GetFileSRC($arFile))) //TODO rename file return CCloudStorage::FILE_SKIPPED; $filePath = "/".$arFile["SUBDIR"]."/".$arFile["FILE_NAME"]; $filePath = preg_replace("#[\\\\\\/]+#", "/", $filePath); if ($arFile["FILE_SIZE"] > $bucket->GetService()->GetMinUploadPartSize()) { $obUpload = new CCloudStorageUpload($filePath); if (!$obUpload->isStarted()) { if ($arFile["HANDLER_ID"]) { $ar = array(); if (!CCloudStorage::OnMakeFileArray($arFile, $ar)) return CCloudStorage::FILE_SKIPPED; if (!isset($ar["tmp_name"])) return CCloudStorage::FILE_SKIPPED; } else { $ar = CFile::MakeFileArray($arFile["ID"]); if (!isset($ar["tmp_name"])) return CCloudStorage::FILE_SKIPPED; } $temp_file = CTempFile::GetDirectoryName(2, "clouds").bx_basename($arFile["FILE_NAME"]); $temp_fileX = $io->GetPhysicalName($temp_file); CheckDirPath($temp_fileX); if (file_exists($ar["tmp_name"])) { $sourceFile = $ar["tmp_name"]; } elseif (file_exists($io->GetPhysicalName($ar["tmp_name"]))) { $sourceFile = $io->GetPhysicalName($ar["tmp_name"]); } else { return CCloudStorage::FILE_SKIPPED; } if (!copy($sourceFile, $temp_fileX)) return CCloudStorage::FILE_SKIPPED; if ($obUpload->Start($bucket->ID, $arFile["FILE_SIZE"], $arFile["CONTENT_TYPE"], $temp_file)) return CCloudStorage::FILE_PARTLY_UPLOADED; else return CCloudStorage::FILE_SKIPPED; } else { $temp_file = $obUpload->getTempFileName(); $temp_fileX = $io->GetPhysicalName($temp_file); $fp = fopen($temp_fileX, "rb"); if (!is_resource($fp)) return CCloudStorage::FILE_SKIPPED; $pos = $obUpload->getPos(); if ($pos > filesize($temp_fileX)) { if ($obUpload->Finish()) { $bucket->IncFileCounter(filesize($temp_fileX)); if ($arFile["HANDLER_ID"]) CCloudStorage::OnFileDelete($arFile); else { $ar = CFile::MakeFileArray($arFile["ID"]); $fileNameX = $io->GetPhysicalName($ar["tmp_name"]); unlink($fileNameX); @rmdir(substr($fileNameX, 0, -strlen(bx_basename($fileNameX)))); } return CCloudStorage::FILE_MOVED; } else return CCloudStorage::FILE_SKIPPED; } fseek($fp, $pos); self::$part_count = $obUpload->GetPartCount(); self::$part_size = $obUpload->getPartSize(); $part = fread($fp, self::$part_size); while ($obUpload->hasRetries()) { if ($obUpload->Next($part)) return CCloudStorage::FILE_PARTLY_UPLOADED; } return CCloudStorage::FILE_SKIPPED; } } else { if ($arFile["HANDLER_ID"]) { $ar = array(); if (!CCloudStorage::OnMakeFileArray($arFile, $ar)) return CCloudStorage::FILE_SKIPPED; if (!isset($ar["tmp_name"])) return CCloudStorage::FILE_SKIPPED; } else { $ar = CFile::MakeFileArray($arFile["ID"]); if (!isset($ar["tmp_name"])) return CCloudStorage::FILE_SKIPPED; } $res = $bucket->SaveFile($filePath, $ar); if ($res) { $bucket->IncFileCounter(filesize($ar["tmp_name"])); if (file_exists($ar["tmp_name"])) { unlink($ar["tmp_name"]); @rmdir(substr($ar["tmp_name"], 0, -strlen(bx_basename($ar["tmp_name"])))); } if ($arFile["HANDLER_ID"]) CCloudStorage::OnFileDelete($arFile); } else { //delete temporary copy if ($arFile["HANDLER_ID"]) { unlink($ar["tmp_name"]); @rmdir(substr($ar["tmp_name"], 0, -strlen(bx_basename($ar["tmp_name"])))); } } return $res? CCloudStorage::FILE_MOVED: CCloudStorage::FILE_SKIPPED; } } public static function OnFileSave(&$arFile, $strFileName, $strSavePath, $bForceMD5 = false, $bSkipExt = false, $dirAdd = '') { if (!$arFile["tmp_name"] && !array_key_exists("content", $arFile)) return false; if (array_key_exists("bucket", $arFile)) $bucket = $arFile["bucket"]; else $bucket = CCloudStorage::FindBucketForFile($arFile, $strFileName); if (!is_object($bucket)) return false; if (!$bucket->Init()) return false; $copySize = false; $subDir = ""; $filePath = ""; if (array_key_exists("content", $arFile)) { $arFile["tmp_name"] = CTempFile::GetFileName($arFile["name"]); CheckDirPath($arFile["tmp_name"]); $fp = fopen($arFile["tmp_name"], "ab"); if ($fp) { fwrite($fp, $arFile["content"]); fclose($fp); } } if (array_key_exists("bucket", $arFile)) { $newName = bx_basename($arFile["tmp_name"]); $prefix = $bucket->GetFileSRC("/"); $subDir = substr($arFile["tmp_name"], strlen($prefix)); $subDir = substr($subDir, 0, -strlen($newName) - 1); } else { if ( $bForceMD5 != true && COption::GetOptionString("main", "save_original_file_name", "N") == "Y" ) { if (COption::GetOptionString("main", "convert_original_file_name", "Y") == "Y") $newName = CCloudStorage::translit($strFileName); else $newName = $strFileName; } else { $strFileExt = ($bSkipExt == true? '': strrchr($strFileName, ".")); $newName = md5(uniqid(mt_rand(), true)).$strFileExt; } //check for double extension vulnerability $newName = RemoveScriptExtension($newName); $dir_add = $dirAdd; if (empty($dir_add)) { while (true) { $dir_add = md5(mt_rand()); $dir_add = substr($dir_add, 0, 3)."/".$dir_add; $subDir = trim($strSavePath, "/")."/".$dir_add; $filePath = "/".$subDir."/".$newName; if (!$bucket->FileExists($filePath)) break; } } else { $subDir = trim($strSavePath, "/")."/".$dir_add; $filePath = "/".$subDir."/".$newName; } $targetPath = $bucket->GetFileSRC("/"); if (strpos($arFile["tmp_name"], $targetPath) === 0) { $arDbFile = array( "SUBDIR" => "", "FILE_NAME" => substr($arFile["tmp_name"], strlen($targetPath)), "CONTENT_TYPE" => $arFile["type"], ); $copyPath = $bucket->FileCopy($arDbFile, $filePath); if (!$copyPath) return false; $copySize = $bucket->GetFileSize("/".urldecode(substr($copyPath, strlen($targetPath)))); } else { $imgArray = CFile::GetImageSize($arFile["tmp_name"], true, false); if (is_array($imgArray) && $imgArray[2] == IMAGETYPE_JPEG) { $exifData = CFile::ExtractImageExif($arFile["tmp_name"]); if ($exifData && isset($exifData['Orientation'])) { $properlyOriented = CFile::ImageHandleOrientation($exifData['Orientation'], $arFile["tmp_name"]); if ($properlyOriented) { $jpgQuality = intval(COption::GetOptionString('main', 'image_resize_quality', '95')); if ($jpgQuality <= 0 || $jpgQuality > 100) $jpgQuality = 95; imagejpeg($properlyOriented, $arFile["tmp_name"], $jpgQuality); clearstatcache(true, $arFile["tmp_name"]); } $arFile['size'] = filesize($arFile["tmp_name"]); } } if (!$bucket->SaveFile($filePath, $arFile)) return false; } } $arFile["HANDLER_ID"] = $bucket->ID; $arFile["SUBDIR"] = $subDir; $arFile["FILE_NAME"] = $newName; $arFile["WIDTH"] = 0; $arFile["HEIGHT"] = 0; if (array_key_exists("bucket", $arFile)) { $arFile["WIDTH"] = $arFile["width"]; $arFile["HEIGHT"] = $arFile["height"]; $arFile["size"] = $arFile["file_size"]; } elseif ($copySize !== false) { $arFile["WIDTH"] = $arFile["width"]; $arFile["HEIGHT"] = $arFile["height"]; $arFile["size"] = $copySize; $bucket->IncFileCounter($copySize); } else { $bucket->IncFileCounter(filesize($arFile["tmp_name"])); $flashEnabled = !CFile::IsImage($arFile["ORIGINAL_NAME"], $arFile["type"]); $imgArray = CFile::GetImageSize($arFile["tmp_name"], true, $flashEnabled); if (is_array($imgArray)) { $arFile["WIDTH"] = $imgArray[0]; $arFile["HEIGHT"] = $imgArray[1]; } } if (isset($arFile["old_file"])) CFile::DoDelete($arFile["old_file"]); return true; } public static function FindBucketByFile($file_name) { foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { if ($bucket["ACTIVE"] == "Y") { $obBucket = new CCloudStorageBucket($bucket["ID"]); if ($obBucket->Init()) { $prefix = $obBucket->GetFileSRC("/"); if (substr($file_name, 0, strlen($prefix)) === $prefix) return $obBucket; } } } return false; } public static function FindFileURIByURN($urn, $log_descr = "") { foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { if ($bucket["ACTIVE"] == "Y") { $obBucket = new CCloudStorageBucket($bucket["ID"]); if ($obBucket->Init() && $obBucket->FileExists($urn)) { $uri = $obBucket->GetFileSRC($urn); if ($log_descr && COption::GetOptionString("clouds", "log_404_errors") === "Y") CEventLog::Log("WARNING", "CLOUDS_404", "clouds", $uri, $log_descr); return $uri; } } } return ""; } public static function OnBuildGlobalMenu(&$aGlobalMenu, &$aModuleMenu) { global $USER; if (!$USER->CanDoOperation("clouds_browse")) return; //When UnRegisterModuleDependences is called from module uninstall //cached EventHandlers may be called if (defined("BX_CLOUDS_UNINSTALLED")) return; $aMenu = array( "parent_menu" => "global_menu_content", "section" => "clouds", "sort" => 150, "text" => GetMessage("CLO_STORAGE_MENU"), "title" => GetMessage("CLO_STORAGE_TITLE"), "icon" => "clouds_menu_icon", "page_icon" => "clouds_page_icon", "items_id" => "menu_clouds", "items" => array() ); $rsBuckets = CCloudStorageBucket::GetList(array("SORT" => "DESC", "ID" => "ASC")); while ($arBucket = $rsBuckets->Fetch()) $aMenu["items"][] = array( "text" => $arBucket["BUCKET"], "url" => "clouds_file_list.php?lang=".LANGUAGE_ID."&bucket=".$arBucket["ID"]."&path=/", "more_url" => array( "clouds_file_list.php?bucket=".$arBucket["ID"], ), "title" => "", "page_icon" => "clouds_page_icon", "items_id" => "menu_clouds_bucket_".$arBucket["ID"], "module_id" => "clouds", "items" => array() ); if (!empty($aMenu["items"])) $aModuleMenu[] = $aMenu; } public static function OnAdminListDisplay(&$obList) { global $USER; if ($obList->table_id !== "tbl_fileman_admin") return; if (!is_object($USER) || !$USER->CanDoOperation("clouds_upload")) return; static $clouds = null; if (!isset($clouds)) { $clouds = array(); $rsClouds = CCloudStorageBucket::GetList(array("SORT" => "DESC", "ID" => "ASC")); while ($arStorage = $rsClouds->Fetch()) { if ($arStorage["READ_ONLY"] == "N" && $arStorage["ACTIVE"] == "Y") $clouds[$arStorage["ID"]] = $arStorage["BUCKET"]; } } if (empty($clouds)) return; foreach ($obList->aRows as $obRow) { if ($obRow->arRes["TYPE"] === "F") { $ID = "F".$obRow->arRes["NAME"]; $file = $obRow->arRes["NAME"]; $path = substr($obRow->arRes["ABS_PATH"], 0, -strlen($file)); $arSubMenu = array(); foreach ($clouds as $id => $bucket) $arSubMenu[] = array( "TEXT" => $bucket, "ACTION" => $s = "if(confirm('".GetMessage("CLO_STORAGE_UPLOAD_CONF")."')) jsUtils.Redirect([], '".CUtil::AddSlashes("/bitrix/admin/clouds_file_list.php?lang=".LANGUAGE_ID."&bucket=".urlencode($id)."&path=".urlencode($path)."&ID=".urlencode($ID)."&action=upload&".bitrix_sessid_get())."');" ); $obRow->aActions[] = array( "TEXT" => GetMessage("CLO_STORAGE_UPLOAD_MENU"), "MENU" => $arSubMenu, ); } } } public static function HasActiveBuckets() { foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) if ($bucket["ACTIVE"] === "Y") return true; return false; } public static function OnBeforeProlog() { if (defined("BX_CHECK_SHORT_URI") && BX_CHECK_SHORT_URI) { $upload_dir = "/".trim(COption::GetOptionString("main", "upload_dir", "upload"), "/")."/"; $request_uri = urldecode($_SERVER["REQUEST_URI"]); $request_uri = CCloudUtil::URLEncode($request_uri, LANG_CHARSET); foreach (CCloudStorageBucket::GetAllBuckets() as $arBucket) { if ($arBucket["ACTIVE"] == "Y") { $obBucket = new CCloudStorageBucket($arBucket["ID"]); if ($obBucket->Init()) { $match = array(); if ( COption::GetOptionString("clouds", "delayed_resize") === "Y" && preg_match("#^(/".$obBucket->PREFIX."|)(/resize_cache/.*\$)#", $request_uri, $match) ) { session_write_close(); $to_file = $obBucket->GetFileSRC(urldecode($match[2])); if (CCloudStorage::ResizeImageFileCheck($obBucket, $to_file)) { $cache_time = 3600 * 24 * 30; // 30 days header("Cache-Control: max-age=".$cache_time); header("Expires: ".gmdate("D, d M Y H:i:s", time() + $cache_time)." GMT"); header_remove("Pragma"); LocalRedirect($to_file, true, "301 Moved Permanently"); } } elseif ( !preg_match("/[?&]/", $request_uri) && $obBucket->FileExists($request_uri) ) { if (COption::GetOptionString("clouds", "log_404_errors") === "Y") CEventLog::Log("WARNING", "CLOUDS_404", "clouds", $_SERVER["REQUEST_URI"], $_SERVER["HTTP_REFERER"]); LocalRedirect($obBucket->GetFileSRC($request_uri), true); } elseif (strpos($request_uri, $upload_dir) === 0) { $check_url = substr($request_uri, strlen($upload_dir) - 1); if ($obBucket->FileExists($check_url)) { if (COption::GetOptionString("clouds", "log_404_errors") === "Y") CEventLog::Log("WARNING", "CLOUDS_404", "clouds", $_SERVER["REQUEST_URI"], $_SERVER["HTTP_REFERER"]); LocalRedirect($obBucket->GetFileSRC($check_url), true); } } } } } } } public static function GetAuditTypes() { return array( "CLOUDS_404" => "[CLOUDS_404] ".GetMessage("CLO_404_ON_MOVED_FILE"), ); } public static function translit($file_name, $safe_chars = '') { return CUtil::translit($file_name, LANGUAGE_ID, array( "safe_chars" => "-. ".$safe_chars, "change_case" => false, "max_len" => 255, )); } /** * @param array [string]string $arFile * @return void */ public static function FixFileContentType(&$arFile) { global $DB; $fixedContentType = ""; if ($arFile["CONTENT_TYPE"] === "image/jpg") $fixedContentType = "image/jpeg"; else { $hexContentType = unpack("H*", $arFile["CONTENT_TYPE"]); if ( $hexContentType[1] === "e0f3e4e8ee2f6d706567" || $hexContentType[1] === "d0b0d183d0b4d0b8d0be2f6d706567" ) $fixedContentType = "audio/mpeg"; } if ($fixedContentType !== "") { $arFile["CONTENT_TYPE"] = $fixedContentType; $DB->Query(" UPDATE b_file SET CONTENT_TYPE = '".$DB->ForSQL($fixedContentType)."' WHERE ID = ".intval($arFile["ID"])." "); CFile::CleanCache($arFile["ID"]); } } } classes/general/security_service_s3.php000064400000021024150241560060014321 0ustar00<? IncludeModuleLangFile(__FILE__); class CCloudSecurityService_AmazonS3 { protected $status = 0; protected $headers = array(); protected $errno = 0; protected $errstr = ''; protected $result = ''; function GetLastRequestStatus() { return $this->status; } function GetObject() { return new CCloudSecurityService_AmazonS3(); } function GetID() { return "amazon_sts"; } function GetName() { return "AWS Security Token Service"; } function GetDefaultBucketControlPolicy($bucket, $prefix) { return array( 'Statement' => array( array( 'Effect' => 'Allow', 'Action' => array( 's3:DeleteObject', 's3:GetObject', 's3:PutObject', 's3:PutObjectAcl' ), 'Resource' => 'arn:aws:s3:::'.$bucket.'/'.$prefix.'/*', ), array( 'Effect' => 'Allow', 'Action' => array( 's3:ListBucket' ), 'Resource' => 'arn:aws:s3:::'.$bucket, 'Condition' => array( 'StringLike' => array( 's3:prefix' => $prefix."/*" ), ), ), ), ); } function GetFederationToken($arBucket, $Policy, $Name, $DurationSeconds = 129600/*36h*/) { global $APPLICATION; $response = $this->SendRequest( $arBucket["SETTINGS"]["ACCESS_KEY"], $arBucket["SETTINGS"]["SECRET_KEY"], 'GET', $arBucket["BUCKET"], '/', array( 'Action' => "GetFederationToken", 'DurationSeconds' => intval($DurationSeconds), 'Name' => $Name, 'Policy' => $this->PHPToJSObject($Policy), ) ); if( is_array($response) && isset($response["GetFederationTokenResponse"]) && is_array($response["GetFederationTokenResponse"]) && isset($response["GetFederationTokenResponse"]["#"]) && is_array($response["GetFederationTokenResponse"]["#"]) && isset($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"]) && is_array($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"]) && isset($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"][0]) && is_array($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"][0]) && isset($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"][0]["#"]) && is_array($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"][0]["#"]) && isset($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"][0]["#"]["Credentials"]) && is_array($response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"][0]["#"]["Credentials"]) ) { $Credentials = $response["GetFederationTokenResponse"]["#"]["GetFederationTokenResult"][0]["#"]["Credentials"]; if( isset($Credentials[0]) && is_array($Credentials[0]) && isset($Credentials[0]["#"]) && is_array($Credentials[0]["#"]) && isset($Credentials[0]["#"]["SessionToken"]) && is_array($Credentials[0]["#"]["SessionToken"]) && isset($Credentials[0]["#"]["SessionToken"][0]) && is_array($Credentials[0]["#"]["SessionToken"][0]) && isset($Credentials[0]["#"]["SessionToken"][0]["#"]) ) $SessionToken = $Credentials[0]["#"]["SessionToken"][0]["#"]; else return 1; if( isset($Credentials[0]) && is_array($Credentials[0]) && isset($Credentials[0]["#"]) && is_array($Credentials[0]["#"]) && isset($Credentials[0]["#"]["SecretAccessKey"]) && is_array($Credentials[0]["#"]["SecretAccessKey"]) && isset($Credentials[0]["#"]["SecretAccessKey"][0]) && is_array($Credentials[0]["#"]["SecretAccessKey"][0]) && isset($Credentials[0]["#"]["SecretAccessKey"][0]["#"]) ) $SecretAccessKey = $Credentials[0]["#"]["SecretAccessKey"][0]["#"]; else return 2; if( isset($Credentials[0]) && is_array($Credentials[0]) && isset($Credentials[0]["#"]) && is_array($Credentials[0]["#"]) && isset($Credentials[0]["#"]["AccessKeyId"]) && is_array($Credentials[0]["#"]["AccessKeyId"]) && isset($Credentials[0]["#"]["AccessKeyId"][0]) && is_array($Credentials[0]["#"]["AccessKeyId"][0]) && isset($Credentials[0]["#"]["AccessKeyId"][0]["#"]) ) $AccessKeyId = $Credentials[0]["#"]["AccessKeyId"][0]["#"]; else return 3; return array( "ACCESS_KEY" => $AccessKeyId, "SECRET_KEY" => $SecretAccessKey, "SESSION_TOKEN" => $SessionToken, ); } else { return false; } } function SendRequest($access_key, $secret_key, $verb, $bucket, $file_name='/', $params='') { global $APPLICATION; $this->status = 0; $RequestMethod = $verb; $RequestHost = "sts.amazonaws.com"; $RequestURI = "/"; $RequestParams = ""; $params['SignatureVersion'] = 2; $params['SignatureMethod'] = 'HmacSHA1'; $params['AWSAccessKeyId'] = $access_key; $params['Timestamp'] = gmdate('Y-m-d').'T'.gmdate('H:i:s');//.preg_replace("/(\d\d)\$/", ":\\1", date("O")); $params['Version'] = '2011-06-15'; ksort($params); foreach($params as $name => $value) { if($RequestParams != '') $RequestParams .= '&'; $RequestParams .= urlencode($name)."=".urlencode($value); } $StringToSign = "$RequestMethod\n" ."$RequestHost\n" ."$RequestURI\n" ."$RequestParams" ; $Signature = urlencode(base64_encode($this->hmacsha1($StringToSign, $secret_key))); $obRequest = new CHTTP; $obRequest->Query($RequestMethod, $RequestHost, 443, $RequestURI."?$RequestParams&Signature=$Signature", false, 'ssl://'); $this->status = $obRequest->status; $this->headers = $obRequest->headers; $this->errno = $obRequest->errno; $this->errstr = $obRequest->errstr; $this->result = $obRequest->result; if($obRequest->status == 200) { if($obRequest->result) { $obXML = new CDataXML; $text = preg_replace("/<"."\\?XML.*?\\?".">/i", "", $obRequest->result); if($obXML->LoadString($text)) { $arXML = $obXML->GetArray(); if(is_array($arXML)) { return $arXML; } } //XML parse error $APPLICATION->ThrowException(GetMessage('CLO_SECSERV_S3_XML_PARSE_ERROR', array('#errno#'=>1))); return false; } else { //Empty success result return array(); } } elseif($obRequest->status > 0) { if($obRequest->result) { $APPLICATION->ThrowException(GetMessage('CLO_SECSERV_S3_XML_ERROR', array('#errmsg#'=>$obRequest->result))); return false; } $APPLICATION->ThrowException(GetMessage('CLO_SECSERV_S3_XML_PARSE_ERROR', array('#errno#'=>2))); return false; } else { $APPLICATION->ThrowException(GetMessage('CLO_SECSERV_S3_XML_PARSE_ERROR', array('#errno#'=>3))); return false; } } function hmacsha1($data, $key) { if(strlen($key)>64) $key=pack('H*', sha1($key)); $key = str_pad($key, 64, chr(0x00)); $ipad = str_repeat(chr(0x36), 64); $opad = str_repeat(chr(0x5c), 64); $hmac = pack('H*', sha1(($key^$opad).pack('H*', sha1(($key^$ipad).$data)))); return $hmac; } function PhpToJSObject($arData, $bWS = false, $bSkipTilda = false) { static $aSearch = array("\r", "\n"); if(is_array($arData)) { if($arData == array_values($arData)) { foreach($arData as $key => $value) { if(is_array($value)) { $arData[$key] = $this->PhpToJSObject($value, $bWS, $bSkipTilda); } elseif(is_bool($value)) { if($value === true) $arData[$key] = 'true'; else $arData[$key] = 'false'; } else { if(preg_match("#['\"\\n\\r<\\\\]#", $value)) $arData[$key] = '"'.CUtil::JSEscape($value).'"'; else $arData[$key] = '"'.$value.'"'; } } return '['.implode(',', $arData).']'; } $sWS = ','.($bWS ? "\n" : ''); $res = ($bWS ? "\n" : '').'{'; $first = true; foreach($arData as $key => $value) { if ($bSkipTilda && substr($key, 0, 1) == '~') continue; if($first) $first = false; else $res .= $sWS; if(preg_match("#['\"\\n\\r<\\\\]#", $key)) $res .= '"'.str_replace($aSearch, '', CUtil::JSEscape($key)).'":'; else $res .= '"'.$key.'":'; if(is_array($value)) { $res .= $this->PhpToJSObject($value, $bWS, $bSkipTilda); } elseif(is_bool($value)) { if($value === true) $res .= 'true'; else $res .= 'false'; } else { if(preg_match("#['\"\\n\\r<\\\\]#", $value)) $res .= '"'.CUtil::JSEscape($value).'"'; else $res .= '"'.$value.'"'; } } $res .= ($bWS ? "\n" : '').'}'; return $res; } elseif(is_bool($arData)) { if($arData === true) return 'true'; else return 'false'; } else { if(preg_match("#['\"\\n\\r<\\\\]#", $arData)) return '"'.CUtil::JSEscape($arData).'"'; else return '"'.$arData.'"'; } } } ?>classes/general/storage_bucket.php000064400000047245150241560060013343 0ustar00<?php IncludeModuleLangFile(__FILE__); /** * @property integer $ID * @property string $ACTIVE * @property integer $SORT * @property string $READ_ONLY * @property string $SERVICE_ID * @property string $BUCKET * @property string $LOCATION * @property string $CNAME * @property integer $FILE_COUNT * @property float $FILE_SIZE * @property integer $LAST_FILE_ID * @property string $PREFIX * @property string $SETTINGS * @property string $FILE_RULES */ class CCloudStorageBucket extends CAllCloudStorageBucket { protected/*.array[string]string.*/$arBucket; /** @var CCloudStorageService $service */ protected/*.CCloudStorageService.*/ $service; protected static/*.array[int][string]string.*/$arBuckets; /** * @param int $ID */ public function __construct($ID) { $this->_ID = intval($ID); } /** * @return array[string]string */ public function getBucketArray() { if(!isset($this->arBucket)) { self::_init(); $this->arBucket = self::$arBuckets[$this->_ID]; } return $this->arBucket; } /** * @return CCloudStorageService */ public function getService() { return $this->service; } /** * @param string $str * @return string */ private function CompileModuleRule($str) { $res = array(); $ar = explode(",", $str); foreach($ar as $s) { $s = trim($s); if($s !== '') $res[$s] = preg_quote($s, '/'); } if(!empty($res)) return "/^(".implode("|", $res).")\$/"; else return ""; } /** * @param string $str * @return string */ private function CompileExtentionRule($str) { $res = array(); $ar = explode(",", $str); foreach($ar as $s) { $s = trim($s); if($s !== '') $res[$s] = preg_quote(".".$s, '/'); } if(!empty($res)) return "/(".implode("|", $res).")\$/i"; else return ""; } /** * @param string $str * @return double */ private function ParseSize($str) { static $scale = array( '' => 1.0, 'K' => 1024.0, 'M' => 1048576.0, 'G' => 1073741824.0, ); $str = strtoupper(trim($str)); if($str !== '' && preg_match("/([0-9.]+)(|K|M|G)\$/", $str, $match) > 0) { return doubleval($match[1])*$scale[$match[2]]; } else { return 0.0; } } /** * @param string $str * @return array[int][int]double */ private function CompileSizeRule($str) { $res = /*.(array[int][int]double).*/array(); $ar = explode(",", $str); foreach($ar as $s) { $s = trim($s); if($s !== '') { $arSize = explode("-", $s); if(count($arSize) == 1) $res[] = array(self::ParseSize($arSize[0]), self::ParseSize($arSize[0])); else $res[] = array(self::ParseSize($arSize[0]), self::ParseSize($arSize[1])); } } return $res; } /** * @param array[int][string]string $arRules * @return array[int][string]string */ private function CompileRules($arRules) { $arCompiled = /*.(array[int][string]string).*/array(); if(is_array($arRules)) { foreach($arRules as $rule) { if(is_array($rule)) { $arCompiled[] = array( "MODULE_MASK" => isset($rule["MODULE"])? self::CompileModuleRule($rule["MODULE"]): "", "EXTENTION_MASK" => isset($rule["EXTENSION"])? self::CompileExtentionRule($rule["EXTENSION"]): "", "SIZE_ARRAY" => isset($rule["SIZE"])? self::CompileSizeRule($rule["SIZE"]): "", ); } } } return $arCompiled; } /** * @return void */ private static function _init() { global $DB, $CACHE_MANAGER; if(isset(self::$arBuckets)) return; $cache_id = "cloud_buckets_v2"; if( CACHED_b_clouds_file_bucket !== false && $CACHE_MANAGER->Read(CACHED_b_clouds_file_bucket, $cache_id, "b_clouds_file_bucket") ) { self::$arBuckets = $CACHE_MANAGER->Get($cache_id); } else { self::$arBuckets = /*.(array[int]CCloudStorageBucket).*/array(); $rs = $DB->Query(" SELECT * FROM b_clouds_file_bucket ORDER BY SORT DESC, ID ASC "); while(is_array($ar = $rs->Fetch())) { if($ar["FILE_RULES"] != "") $arRules = unserialize($ar["FILE_RULES"]); else $arRules = array(); $ar["FILE_RULES_COMPILED"] = self::CompileRules($arRules); if($ar["SETTINGS"] != "") $arSettings = unserialize($ar["SETTINGS"]); else $arSettings = array(); if(is_array($arSettings)) $ar["SETTINGS"] = $arSettings; else $ar["SETTINGS"] = array(); self::$arBuckets[intval($ar['ID'])] = $ar; } if(CACHED_b_clouds_file_bucket !== false) $CACHE_MANAGER->Set($cache_id, self::$arBuckets); } } /** * @param string $name * @return mixed */ function __get($name) { if(!isset($this->arBucket)) { self::_init(); $this->arBucket = self::$arBuckets[$this->_ID]; } if(isset($this->arBucket) && array_key_exists($name, $this->arBucket)) return $this->arBucket[$name]; else return null; } /** * @return bool */ function Init() { if(is_object($this->service)) { return true; } else { if($this->SERVICE_ID) $this->service = CCloudStorage::GetServiceByID($this->SERVICE_ID); return is_object($this->service); } } /** * @return bool */ function RenewToken() { if ($this->service->tokenHasExpired) { $newSettings = false; foreach(GetModuleEvents("clouds", "OnExpiredToken", true) as $arEvent) { $newSettings = ExecuteModuleEventEx($arEvent, array($this->arBucket)); if ($newSettings) break; } if ($newSettings) { $updateResult = $this->Update(array("SETTINGS" => $newSettings)); if ($updateResult) { $this->service->tokenHasExpired = false; return true; } } } return false; } /** * @param array[string]string $arSettings * @return bool */ function CheckSettings(&$arSettings) { return $this->service->CheckSettings($this->arBucket, $arSettings); } /** * @return bool */ function CreateBucket() { return $this->service->CreateBucket($this->arBucket); } /** * @param mixed $arFile * @return string */ function GetFileSRC($arFile) { if(is_array($arFile) && isset($arFile["URN"])) return $this->service->GetFileSRC($this->arBucket, $arFile["URN"]); else return preg_replace("'(?<!:)/+'s", "/", $this->service->GetFileSRC($this->arBucket, $arFile)); } /** * @param string $filePath * @return bool */ function FileExists($filePath) { return $this->service->FileExists($this->arBucket, $filePath); } /** * @param mixed $arFile * @param string $filePath * @return bool */ function DownloadToFile($arFile, $filePath) { return $this->service->DownloadToFile($this->arBucket, $arFile, $filePath); } /** * @param string $filePath * @param mixed $arFile * @return bool */ function SaveFile($filePath, $arFile) { $result = $this->service->SaveFile($this->arBucket, $filePath, $arFile); if (!$result && $this->RenewToken()) { $result = $this->service->SaveFile($this->getBucketArray(), $filePath, $arFile); } if ($result) { foreach(GetModuleEvents("clouds", "OnAfterSaveFile", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($this, $arFile, $filePath)); } } return $result; } /** * @param string $filePath * @return bool */ function DeleteFile($filePath) { $result = $this->service->DeleteFile($this->arBucket, $filePath); if ($result) { foreach(GetModuleEvents("clouds", "OnAfterDeleteFile", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($this, array('del' => 'Y'), $filePath)); } } return $result; } /** * @param mixed $arFile * @param string $filePath * @return bool */ function FileCopy($arFile, $filePath) { $result = $this->service->FileCopy($this->arBucket, $arFile, $filePath); if ($result) { foreach(GetModuleEvents("clouds", "OnAfterCopyFile", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($this, $arFile, $filePath)); } } return $result; } /** * @param string $sourcePath * @param string $targetPath * @param bool $overwrite * @return bool */ function FileRename($sourcePath, $targetPath, $overwrite = true) { $result = $this->service->FileRename($this->arBucket, $sourcePath, $targetPath, $overwrite); if ($result) { foreach(GetModuleEvents("clouds", "OnAfterRenameFile", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($this, $sourcePath, $targetFile)); } } return $result; } /** * @param string $filePath * @param bool $bRecursive * @return array[string][int]string */ function ListFiles($filePath = "/", $bRecursive = false) { $result = $this->service->ListFiles($this->arBucket, $filePath, $bRecursive); if (!$result && $this->RenewToken()) { $result = $this->service->ListFiles($this->getBucketArray(), $filePath, $bRecursive); } return $result; } /** * @param string $filePath * @return double */ function GetFileSize($filePath) { $DIR_NAME = substr($filePath, 0, strrpos($filePath, "/") + 1); $FILE_NAME = substr($filePath, strlen($DIR_NAME)); $arListing = $this->service->ListFiles($this->arBucket, $DIR_NAME, false); if(is_array($arListing)) { foreach($arListing["file"] as $i => $name) if($name === $FILE_NAME) return doubleval($arListing["file_size"][$i]); } return 0.0; } /** * @return array[int][string]string */ static function GetAllBuckets() { self::_init(); return self::$arBuckets; } /** * @param array[string]string $arFields * @param int $ID * @return bool */ function CheckFields(&$arFields, $ID) { global $APPLICATION; $aMsg = array(); if(array_key_exists("ACTIVE", $arFields)) $arFields["ACTIVE"] = $arFields["ACTIVE"] === "N"? "N": "Y"; if(array_key_exists("READ_ONLY", $arFields)) $arFields["READ_ONLY"] = $arFields["READ_ONLY"] === "Y"? "Y": "N"; $arServices = CCloudStorage::GetServiceList(); if(isset($arFields["SERVICE_ID"])) { if(!array_key_exists($arFields["SERVICE_ID"], $arServices)) $aMsg[] = array("id" => "SERVICE_ID", "text" => GetMessage("CLO_STORAGE_WRONG_SERVICE")); } if(isset($arFields["BUCKET"])) { $arFields["BUCKET"] = trim($arFields["BUCKET"]); $bBadLength = false; if(strpos($arFields["BUCKET"], ".") !== false) { $arName = explode(".", $arFields["BUCKET"]); $bBadLength = false; foreach($arName as $str) if(strlen($str) < 2 || strlen($str) > 63) $bBadLength = true; } if(strlen($arFields["BUCKET"]) <= 0) $aMsg[] = array("id" => "BUCKET", "text" => GetMessage("CLO_STORAGE_EMPTY_BUCKET")); if(preg_match("/[^a-z0-9._-]/", $arFields["BUCKET"]) > 0) $aMsg[] = array("id" => "BUCKET", "text" => GetMessage("CLO_STORAGE_BAD_BUCKET_NAME")); if(strlen($arFields["BUCKET"]) < 2 || strlen($arFields["BUCKET"]) > 63) $aMsg[] = array("id" => "BUCKET", "text" => GetMessage("CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH")); if($bBadLength) $aMsg[] = array("id" => "BUCKET", "text" => GetMessage("CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH2")); if(!preg_match("/^[a-z0-9].*[a-z0-9]\$/", $arFields["BUCKET"])) $aMsg[] = array("id" => "BUCKET", "text" => GetMessage("CLO_STORAGE_BAD_BUCKET_NAME2")); if(preg_match("/(-\\.|\\.-)/", $arFields["BUCKET"]) > 0) $aMsg[] = array("id" => "BUCKET", "text" => GetMessage("CLO_STORAGE_BAD_BUCKET_NAME3")); if(strlen($arFields["BUCKET"]) > 0) { $rsBucket = self::GetList(array(), array( "=SERVICE_ID" => $arFields["SERVICE_ID"], "=BUCKET" => $arFields["BUCKET"], )); $arBucket = $rsBucket->Fetch(); if(is_array($arBucket) && $arBucket["ID"] != $ID) $aMsg[] = array("id" => "BUCKET", "text" => GetMessage("CLO_STORAGE_BUCKET_ALREADY_EXISTS")); } } if(!empty($aMsg)) { $e = new CAdminException($aMsg); $APPLICATION->ThrowException($e); return false; } return true; } /** * @param array[string]string $arOrder * @param array[string]string $arFilter * @param array[string]string $arSelect * @return CDBResult */ static function GetList($arOrder=false, $arFilter=false, $arSelect=false) { global $DB; if(!is_array($arSelect)) $arSelect =/*.(array[string]string).*/array(); if(count($arSelect) < 1) $arSelect = array( "ID", "ACTIVE", "READ_ONLY", "SORT", "SERVICE_ID", "LOCATION", "BUCKET", "SETTINGS", "CNAME", "PREFIX", "FILE_COUNT", "FILE_SIZE", "LAST_FILE_ID", "FILE_RULES", ); if(!is_array($arOrder)) $arOrder =/*.(array[string]string).*/array(); $arQueryOrder = array(); foreach($arOrder as $strColumn => $strDirection) { $strColumn = strtoupper($strColumn); $strDirection = strtoupper($strDirection)==="ASC"? "ASC": "DESC"; switch($strColumn) { case "ID": case "SORT": $arSelect[] = $strColumn; $arQueryOrder[$strColumn] = $strColumn." ".$strDirection; break; default: break; } } $arQuerySelect = array(); foreach($arSelect as $strColumn) { $strColumn = strtoupper($strColumn); switch($strColumn) { case "ID": case "ACTIVE": case "READ_ONLY": case "SORT": case "SERVICE_ID": case "LOCATION": case "BUCKET": case "SETTINGS": case "CNAME": case "PREFIX": case "FILE_COUNT": case "FILE_SIZE": case "LAST_FILE_ID": case "FILE_RULES": $arQuerySelect[$strColumn] = "s.".$strColumn; break; } } if(count($arQuerySelect) < 1) $arQuerySelect = array("ID"=>"s.ID"); $obQueryWhere = new CSQLWhere; $arFields = array( "ID" => array( "TABLE_ALIAS" => "s", "FIELD_NAME" => "s.ID", "FIELD_TYPE" => "int", ), "ACTIVE" => array( "TABLE_ALIAS" => "s", "FIELD_NAME" => "s.ACTIVE", "FIELD_TYPE" => "string", ), "READ_ONLY" => array( "TABLE_ALIAS" => "s", "FIELD_NAME" => "s.READ_ONLY", "FIELD_TYPE" => "string", ), "SERVICE_ID" => array( "TABLE_ALIAS" => "s", "FIELD_NAME" => "s.SERVICE_ID", "FIELD_TYPE" => "string", ), "BUCKET" => array( "TABLE_ALIAS" => "s", "FIELD_NAME" => "s.BUCKET", "FIELD_TYPE" => "string", ), ); $obQueryWhere->SetFields($arFields); if(!is_array($arFilter)) $arFilter =/*.(array[string]string).*/array(); $strQueryWhere = $obQueryWhere->GetQuery($arFilter); $bDistinct = $obQueryWhere->bDistinctReqired; $strSql = " SELECT ".($bDistinct? "DISTINCT": "")." ".implode(", ", $arQuerySelect)." FROM b_clouds_file_bucket s ".$obQueryWhere->GetJoins()." "; if($strQueryWhere != "") { $strSql .= " WHERE ".$strQueryWhere." "; } if(count($arQueryOrder) > 0) { $strSql .= " ORDER BY ".implode(", ", $arQueryOrder)." "; } return $DB->Query($strSql); } /** * @param array[string]string $arFields * @return mixed */ function Add($arFields) { global $DB, $APPLICATION, $CACHE_MANAGER; $strError = ''; $this->_ID = 0; if(!$this->CheckFields($arFields, 0)) return false; $arFields["FILE_COUNT"] = 0; if(is_array($arFields["FILE_RULES"])) $arFields["FILE_RULES"] = serialize($arFields["FILE_RULES"]); else $arFields["FILE_RULES"] = false; $this->arBucket = $arFields; if($this->Init()) { if(!$this->CheckSettings($arFields["SETTINGS"])) return false; $this->arBucket["SETTINGS"] = $arFields["SETTINGS"]; if($this->CreateBucket()) { $arFields["SETTINGS"] = serialize($arFields["SETTINGS"]); $this->_ID = $DB->Add("b_clouds_file_bucket", $arFields); self::$arBuckets = null; $this->arBucket = null; if(CACHED_b_clouds_file_bucket !== false) $CACHE_MANAGER->CleanDir("b_clouds_file_bucket"); return $this->_ID; } else { $e = $APPLICATION->GetException(); if(is_object($e)) $strError = GetMessage("CLO_STORAGE_CLOUD_ADD_ERROR", array("#error_msg#" => $e->GetString())); else $strError = GetMessage("CLO_STORAGE_CLOUD_ADD_ERROR", array("#error_msg#" => 'CSB42343')); } } else { $strError = GetMessage("CLO_STORAGE_CLOUD_ADD_ERROR", array("#error_msg#" => GetMessage("CLO_STORAGE_UNKNOWN_SERVICE"))); } $APPLICATION->ResetException(); $e = new CApplicationException($strError); $APPLICATION->ThrowException($e); return false; } /** * @return bool */ function Delete() { global $DB, $APPLICATION, $CACHE_MANAGER; $strError = ''; if($this->Init()) { if($this->service->IsEmptyBucket($this->arBucket)) { if($this->service->DeleteBucket($this->arBucket)) { $res = $DB->Query("DELETE FROM b_clouds_file_bucket WHERE ID = ".$this->_ID); if(CACHED_b_clouds_file_bucket !== false) $CACHE_MANAGER->CleanDir("b_clouds_file_bucket"); if(is_object($res)) { $this->arBucket = null; $this->_ID = 0; return true; } else { $strError = GetMessage("CLO_STORAGE_DB_DELETE_ERROR"); } } else { $e = $APPLICATION->GetException(); $strError = GetMessage("CLO_STORAGE_CLOUD_DELETE_ERROR", array("#error_msg#" => is_object($e)? $e->GetString(): '')); } } else { $e = $APPLICATION->GetException(); if(is_object($e)) $strError = GetMessage("CLO_STORAGE_CLOUD_DELETE_ERROR", array("#error_msg#" => $e->GetString())); else $strError = GetMessage("CLO_STORAGE_CLOUD_BUCKET_NOT_EMPTY"); } } else { $strError = GetMessage("CLO_STORAGE_CLOUD_DELETE_ERROR", array("#error_msg#" => GetMessage("CLO_STORAGE_UNKNOWN_SERVICE"))); } $APPLICATION->ResetException(); $e = new CApplicationException($strError); $APPLICATION->ThrowException($e); return false; } /** * @param array[string]string $arFields * @return mixed */ function Update($arFields) { global $DB, $CACHE_MANAGER; if($this->_ID <= 0) return false; $this->service = CCloudStorage::GetServiceByID($this->SERVICE_ID); if(!is_object($this->service)) return false; unset($arFields["FILE_COUNT"]); unset($arFields["SERVICE_ID"]); unset($arFields["LOCATION"]); unset($arFields["BUCKET"]); if(!$this->CheckFields($arFields, $this->_ID)) return false; if(array_key_exists("FILE_RULES", $arFields)) { if(is_array($arFields["FILE_RULES"])) $arFields["FILE_RULES"] = serialize($arFields["FILE_RULES"]); else $arFields["FILE_RULES"] = false; } if(array_key_exists("SETTINGS", $arFields)) { if(!$this->CheckSettings($arFields["SETTINGS"])) return false; $arFields["SETTINGS"] = serialize($arFields["SETTINGS"]); } $strUpdate = $DB->PrepareUpdate("b_clouds_file_bucket", $arFields); if(strlen($strUpdate) > 0) { $strSql = " UPDATE b_clouds_file_bucket SET ".$strUpdate." WHERE ID = ".$this->_ID." "; if(!is_object($DB->Query($strSql))) return false; } self::$arBuckets = null; $this->arBucket = null; if(CACHED_b_clouds_file_bucket !== false) $CACHE_MANAGER->CleanDir("b_clouds_file_bucket"); return $this->_ID; } /** * @param array[string][int]string $arPOST * @return array[int][string]string */ static function ConvertPOST($arPOST) { $arRules =/*.(array[int][string]string).*/array(); if(isset($arPOST["MODULE"]) && is_array($arPOST["MODULE"])) { foreach($arPOST["MODULE"] as $i => $MODULE) { if(!isset($arRules[intval($i)])) $arRules[intval($i)] = array("MODULE" => "", "EXTENSION" => "", "SIZE" => ""); $arRules[intval($i)]["MODULE"] = $MODULE; } } if(isset($arPOST["EXTENSION"]) && is_array($arPOST["EXTENSION"])) { foreach($arPOST["EXTENSION"] as $i => $EXTENSION) { if(!isset($arRules[intval($i)])) $arRules[intval($i)] = array("MODULE" => "", "EXTENSION" => "", "SIZE" => ""); $arRules[intval($i)]["EXTENSION"] = $EXTENSION; } } if(isset($arPOST["SIZE"]) && is_array($arPOST["SIZE"])) { foreach($arPOST["SIZE"] as $i => $SIZE) { if(!isset($arRules[intval($i)])) $arRules[intval($i)] = array("MODULE" => "", "EXTENSION" => "", "SIZE" => ""); $arRules[intval($i)]["SIZE"] = $SIZE; } } return $arRules; } /** * @param string $name * @param string $value * @return void */ function setHeader($name, $value) { $this->service->setHeader($name, $value); } } classes/mysql/storage_bucket.php000064400000002744150241560060013066 0ustar00<?php class CAllCloudStorageBucket { protected/*.int.*/$_ID = 0; /** * @param double $file_size * @param int $file_count * @return CDBResult */ public function SetFileCounter($file_size, $file_count) { global $DB, $CACHE_MANAGER; $res = $DB->Query(" UPDATE b_clouds_file_bucket SET FILE_COUNT = ".intval($file_count)." ,FILE_SIZE = ".roundDB($file_size)." WHERE ID = ".$this->_ID." "); if(CACHED_b_clouds_file_bucket !== false) $CACHE_MANAGER->CleanDir("b_clouds_file_bucket"); return $res; } /** * @param double $file_size * @return CDBResult */ function IncFileCounter($file_size = 0.0) { global $DB, $CACHE_MANAGER; $res = $DB->Query(" UPDATE b_clouds_file_bucket SET FILE_COUNT = FILE_COUNT + 1 ".($file_size > 0.0? ",FILE_SIZE = FILE_SIZE + ".roundDB($file_size): "")." WHERE ID = ".$this->_ID." "); if(CACHED_b_clouds_file_bucket !== false) $CACHE_MANAGER->CleanDir("b_clouds_file_bucket"); return $res; } /** * @param double $file_size * @return CDBResult */ function DecFileCounter($file_size = 0.0) { global $DB, $CACHE_MANAGER; $res = $DB->Query(" UPDATE b_clouds_file_bucket SET FILE_COUNT = FILE_COUNT - 1 ".($file_size > 0.0? ",FILE_SIZE = if(FILE_SIZE - ".roundDB($file_size)." > 0, FILE_SIZE - ".roundDB($file_size).", 0)": "")." WHERE ID = ".$this->_ID." AND FILE_COUNT > 0 "); if(CACHED_b_clouds_file_bucket !== false) $CACHE_MANAGER->CleanDir("b_clouds_file_bucket"); return $res; } } admin/task_description.php000064400000001411150241560060011706 0ustar00<? if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die(); use Bitrix\Main\Localization\Loc; Loc::loadMessages(__FILE__); return array( "CLOUDS_DENIED" => array( "title" => Loc::getMessage('TASK_NAME_CLOUDS_DENIED'), "description" => Loc::getMessage('TASK_DESC_CLOUDS_DENIED'), ), "CLOUDS_BROWSE" => array( "title" => Loc::getMessage('TASK_NAME_CLOUDS_BROWSE'), "description" => Loc::getMessage('TASK_DESC_CLOUDS_BROWSE'), ), "CLOUDS_UPLOAD" => array( "title" => Loc::getMessage('TASK_NAME_CLOUDS_UPLOAD'), "description" => Loc::getMessage('TASK_DESC_CLOUDS_UPLOAD'), ), "CLOUDS_FULL_ACCESS" => array( "title" => Loc::getMessage('TASK_NAME_CLOUDS_FULL_ACCESS'), "description" => Loc::getMessage('TASK_DESC_CLOUDS_FULL_ACCESS'), ), ); admin/menu.php000064400000001064150241560060007311 0ustar00<? /*.require_module 'bitrix_main_include_prolog_admin_before';.*/ IncludeModuleLangFile(__FILE__); if(!$USER->CanDoOperation("clouds_config")) return false; $arMenu = array( "parent_menu" => "global_menu_settings", "section" => "clouds", "sort" => 1650, "text" => GetMessage("CLO_MENU_ITEM"), "title" => GetMessage("CLO_MENU_TITLE"), "url" => "clouds_storage_list.php?lang=".LANGUAGE_ID, "more_url" => array("clouds_storage_list.php", "clouds_storage_edit.php"), "icon" => "clouds_menu_icon", "page_icon" => "clouds_page_icon", ); return $arMenu; ?> admin/clouds_storage_list.php000064400000034545150241560060012427 0ustar00<? define("ADMIN_MODULE_NAME", "clouds"); /*.require_module 'standard';.*/ /*.require_module 'pcre';.*/ /*.require_module 'bitrix_main_include_prolog_admin_before';.*/ require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php"); if(!$USER->CanDoOperation("clouds_config")) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); /*.require_module 'bitrix_clouds_include';.*/ if(!CModule::IncludeModule('clouds')) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); IncludeModuleLangFile(__FILE__); $io = CBXVirtualIo::GetInstance(); $sTableID = "tbl_clouds_storage_list"; $oSort = new CAdminSorting($sTableID, "ID", "ASC"); $lAdmin = new CAdminList($sTableID, $oSort); $bOnTheMove = isset($_GET["themove"]); $upload_dir = $_SERVER["DOCUMENT_ROOT"]."/".COption::GetOptionString("main", "upload_dir", "upload"); $bHasLocalStorage = file_exists($upload_dir) && (is_dir($upload_dir) || is_link($upload_dir)) && is_writable($upload_dir); $arID = $lAdmin->GroupAction(); $action = isset($_REQUEST["action"]) && is_string($_REQUEST["action"])? "$_REQUEST[action]": ""; if(is_array($arID)) { foreach($arID as $ID) { if(strlen($ID) <= 0 || intval($ID) <= 0) continue; switch($action) { case "delete": $ob = new CCloudStorageBucket(intval($ID)); if(!$ob->Delete()) { $e = $APPLICATION->GetException(); $lAdmin->AddUpdateError($e->GetString(), $ID); } break; case "deactivate": $ob = new CCloudStorageBucket(intval($ID)); if($ob->ACTIVE === "Y") $ob->Update(array("ACTIVE"=>"N")); break; case "activate": $ob = new CCloudStorageBucket(intval($ID)); if($ob->ACTIVE === "N") $ob->Update(array("ACTIVE"=>"Y")); break; case "download": $ob = new CCloudStorageBucket(intval($ID)); if($ob->Init() && $ob->ACTIVE === "Y") { if(isset($_SESSION["last_file_id"])) $last_file_id = intval($_SESSION["last_file_id"]); else $last_file_id = 0; if(isset($_SESSION["last_file_pos"])) $last_file_pos = doubleval($_SESSION["last_file_pos"]); else $last_file_pos = 0; $rsNextFile = $DB->Query(" SELECT MIN(ID) ID, COUNT(1) CNT, SUM(FILE_SIZE) FILE_SIZE FROM b_file WHERE ID > ".intval($last_file_id)." AND HANDLER_ID = '".$DB->ForSQL($ob->ID)."' "); $lAdmin->BeginPrologContent(); if( is_array($ar = $rsNextFile->Fetch()) && (intval($ar["ID"]) > 0) ) { $bNextFile = true; $bFileMoved = false; $maxPartSize = 1024*1024; //1M $arFile = CFile::GetFileArray($ar["ID"]); $filePath = preg_replace("#[\\\\\\/]+#", "/", "/".$arFile["SUBDIR"]."/".$arFile["FILE_NAME"]); $absPath = preg_replace("#[\\\\\\/]+#", "/", $_SERVER["DOCUMENT_ROOT"]."/".COption::GetOptionString("main", "upload_dir", "upload").$filePath); $absPath = $io->GetPhysicalName($absPath); $absTempPath = $absPath."~"; if(!file_exists($absPath)) { CheckDirPath($absTempPath); $obRequest = new CHTTP; $obRequest->follow_redirect = true; $obRequest->fp = fopen($absTempPath, "ab"); if(is_resource($obRequest->fp)) { if($arFile["FILE_SIZE"] > $maxPartSize) { $obRequest->additional_headers["Range"] = sprintf("bytes=%u-%u", $last_file_pos, ($last_file_pos+$maxPartSize > $arFile["FILE_SIZE"]? $arFile["FILE_SIZE"]: $last_file_pos+$maxPartSize)-1); } $res = $obRequest->HTTPQuery('GET', $ob->GetFileSRC($arFile)); fclose($obRequest->fp); unset($obRequest->fp); if($res && ($obRequest->status == 200 || $obRequest->status == 206)) { $bFileMoved = true; if($arFile["FILE_SIZE"] > $maxPartSize) { $last_file_pos += $maxPartSize; $_SESSION["last_file_pos"] = $last_file_pos; $bNextFile = false; } else { $last_file_pos = $arFile["FILE_SIZE"]; } if( array_key_exists("Content-Range", $obRequest->headers) && preg_match("/(\\d+)-(\\d+)\\/(\\d+)\$/", $obRequest->headers["Content-Range"], $match) ) $FILE_SIZE = $match[3]; elseif( array_key_exists("Content-Length", $obRequest->headers) && preg_match("/^(\\d+)\$/", $obRequest->headers["Content-Length"], $match) && $match[1] > $maxPartSize ) $FILE_SIZE = 0; //Chunk download not supported else $FILE_SIZE = $arFile["FILE_SIZE"]; if($last_file_pos > $FILE_SIZE) { $last_file_pos = $arFile["FILE_SIZE"]; $bFileMoved = true; $bNextFile = true; } } else { //An error occured @unlink($absTempPath); $bFileMoved = false; } } } if($bNextFile) { $_SESSION["last_file_id"] = $ar["ID"]; $_SESSION["last_file_pos"] = 0.0; if($bFileMoved) { rename($absTempPath, $absPath); $ob->DeleteFile($filePath); $DB->Query(" UPDATE b_file SET HANDLER_ID = null WHERE ID = ".intval($arFile["ID"])." "); CFile::CleanCache($arFile["ID"]); $ob->DecFileCounter((float)$arFile["FILE_SIZE"]); $ob->Update(array("LAST_FILE_ID" => 0)); } } CAdminMessage::ShowMessage(array( "TYPE"=>"PROGRESS", "MESSAGE"=>GetMessage("CLO_STORAGE_LIST_DOWNLOAD_IN_PROGRESS"), "DETAILS"=>GetMessage("CLO_STORAGE_LIST_DOWNLOAD_PROGRESS", array( "#remain#" => $ar["CNT"] - $bNextFile, "#bytes#" => CFile::FormatSize($ar["FILE_SIZE"] - $last_file_pos), )), "HTML"=>true, "BUTTONS" => array( array( "VALUE" => GetMessage("CLO_STORAGE_LIST_STOP"), "ONCLICK" => 'window.location = \'/bitrix/admin/clouds_storage_list.php?lang='.LANGUAGE_ID.'\'', ), ), )); $bOnTheMove = true; echo '<script>', $lAdmin->ActionDoGroup($ID, "download", "themove=y"), '</script>'; } else { unset($_SESSION["last_file_id"]); unset($_SESSION["last_file_pos"]); CAdminMessage::ShowMessage(array( "MESSAGE"=>GetMessage("CLO_STORAGE_LIST_DOWNLOAD_DONE"), "TYPE"=>"OK", "HTML"=>true, )); $bOnTheMove = false; } $lAdmin->EndPrologContent(); } break; case "move": $message = /*.(CAdminMessage).*/null; $ob = new CCloudStorageBucket(intval($ID)); if($ob->ACTIVE === "Y" && $ob->READ_ONLY === "N") { $_done = 0; $_size = 0.0; $_skip = 0; if(intval($ob->LAST_FILE_ID) > 0) { if(isset($_SESSION["arMoveStat_done"])) $_done = intval($_SESSION["arMoveStat_done"]); if(isset($_SESSION["arMoveStat_size"])) $_size = doubleval($_SESSION["arMoveStat_size"]); if(isset($_SESSION["arMoveStat_skip"])) $_skip = intval($_SESSION["arMoveStat_skip"]); } $files_per_step = 50; $rsNextFile = $DB->Query($DB->TopSQL(" SELECT * FROM b_file WHERE ID > ".intval($ob->LAST_FILE_ID)." AND (HANDLER_ID IS NULL OR HANDLER_ID <> '".$DB->ForSQL($ob->ID)."') ORDER BY ID ASC ", $files_per_step)); $counter = 0; $bWasMoved = false; $moveResult = CCloudStorage::FILE_SKIPPED; while( $moveResult == CCloudStorage::FILE_PARTLY_UPLOADED || is_array($arFile = $rsNextFile->Fetch()) ) { CCloudStorage::FixFileContentType($arFile); $moveResult = CCloudStorage::MoveFile($arFile, $ob); if($moveResult == CCloudStorage::FILE_MOVED) { $DB->Query(" UPDATE b_file SET HANDLER_ID = '".$DB->ForSQL($ob->ID)."' WHERE ID = ".intval($arFile["ID"])." "); CFile::CleanCache($arFile["ID"]); $_done += 1; $_size += doubleval($arFile["FILE_SIZE"]); $bWasMoved = true; $ob->Update(array("LAST_FILE_ID" => $arFile["ID"])); $counter++; } elseif($moveResult == CCloudStorage::FILE_SKIPPED) { $e = $APPLICATION->GetException(); if(is_object($e)) { $message = new CAdminMessage(GetMessage("CLO_STORAGE_LIST_MOVE_FILE_ERROR"), $e); break; } else { $_skip += 1; $ob->Update(array("LAST_FILE_ID" => $arFile["ID"])); $counter++; } } else//if($moveResult == CCloudStorage::FILE_PARTLY_UPLOADED) { $bWasMoved = true; } if($bWasMoved) { usleep(300); break; } } $lAdmin->BeginPrologContent(); if(is_object($message)) { echo $message->Show(); } elseif($counter < $files_per_step && !$bWasMoved) { CAdminMessage::ShowMessage(array( "MESSAGE"=>GetMessage("CLO_STORAGE_LIST_MOVE_DONE"), "DETAILS"=>GetMessage("CLO_STORAGE_LIST_MOVE_PROGRESS", array( "#bytes#" => CFile::FormatSize($_size), "#total#" => $_done + $_skip, "#moved#" => $_done, "#skiped#" => $_skip, )), "HTML"=>true, "TYPE"=>"OK", )); $bOnTheMove = false; $ob->Update(array("LAST_FILE_ID" => false)); } else { CAdminMessage::ShowMessage(array( "TYPE"=>"PROGRESS", "MESSAGE"=>GetMessage("CLO_STORAGE_LIST_MOVE_IN_PROGRESS"), "DETAILS"=>GetMessage("CLO_STORAGE_LIST_MOVE_PROGRESS", array( "#bytes#" => CFile::FormatSize($_size + CCloudStorage::$part_count*CCloudStorage::$part_size), "#total#" => $_done + $_skip, "#moved#" => $_done, "#skiped#" => $_skip, )), "HTML"=>true, "BUTTONS" => array( array( "VALUE" => GetMessage("CLO_STORAGE_LIST_STOP"), "ONCLICK" => 'window.location = \'/bitrix/admin/clouds_storage_list.php?lang='.LANGUAGE_ID.'\'', ), ), )); $bOnTheMove = true; echo '<script>', $lAdmin->ActionDoGroup($ID, "move", "themove=y"), '</script>'; } $lAdmin->EndPrologContent(); $_SESSION["arMoveStat_done"] = $_done; $_SESSION["arMoveStat_size"] = $_size; $_SESSION["arMoveStat_skip"] = $_skip; } break; default: break; } } } $arHeaders = array( array( "id" => "SORT", "content" => GetMessage("CLO_STORAGE_LIST_SORT"), "align" => "right", "default" => true, ), array( "id" => "ID", "content" => GetMessage("CLO_STORAGE_LIST_ID"), "align" => "right", "default" => true, ), array( "id" => "ACTIVE", "content" => GetMessage("CLO_STORAGE_LIST_ACTIVE"), "align" => "center", "default" => true, ), array( "id" => "FILE_COUNT", "content" => GetMessage("CLO_STORAGE_LIST_FILE_COUNT"), "align" => "right", "default" => true, ), array( "id" => "FILE_SIZE", "content" => GetMessage("CLO_STORAGE_LIST_FILE_SIZE"), "align" => "right", "default" => true, ), array( "id" => "READ_ONLY", "content" => GetMessage("CLO_STORAGE_LIST_MODE"), "align" => "center", "default" => true, ), array( "id" => "SERVICE", "content" => GetMessage("CLO_STORAGE_LIST_SERVICE"), "default" => true, ), array( "id" => "BUCKET", "content" => GetMessage("CLO_STORAGE_LIST_BUCKET"), "align" => "center", "default" => true, ), ); $lAdmin->AddHeaders($arHeaders); $rsData = CCloudStorageBucket::GetList(array("SORT"=>"DESC", "ID"=>"ASC")); $rsData = new CAdminResult($rsData, $sTableID); while(is_array($arRes = $rsData->Fetch())) { $row =& $lAdmin->AddRow($arRes["ID"], $arRes); $row->AddViewField("ID", '<a href="clouds_storage_edit.php?lang='.LANGUAGE_ID.'&ID='.$arRes["ID"].'">'.$arRes["ID"].'</a>'); if($arRes["ACTIVE"] === "Y") $html = '<div class="lamp-green"></div>'; else $html = '<div class="lamp-red"></div>'; $row->AddViewField("ACTIVE", $html); $row->AddViewField("READ_ONLY", $arRes["READ_ONLY"]==="Y"? GetMessage("CLO_STORAGE_LIST_READ_ONLY"): GetMessage("CLO_STORAGE_LIST_READ_WRITE")); $row->AddViewField("SERVICE", CCloudStorage::GetServiceDescription($arRes["SERVICE_ID"])); $row->AddViewField("FILE_SIZE", CFile::FormatSize($arRes["FILE_SIZE"])); $arActions = array( array( "ICON" => "edit", "DEFAULT" => true, "TEXT" => GetMessage("CLO_STORAGE_LIST_EDIT"), "ACTION" => $lAdmin->ActionRedirect('clouds_storage_edit.php?lang='.LANGUAGE_ID.'&ID='.$arRes["ID"]) ) ); $arActions[] = array("SEPARATOR"=>"Y"); if($arRes["ACTIVE"] === "Y") { if($arRes["READ_ONLY"] !== "Y") { if(intval($arRes["LAST_FILE_ID"]) > 0) { $arActions[] = array( "TEXT"=>GetMessage("CLO_STORAGE_LIST_CONT_MOVE_FILES"), "ACTION"=>$lAdmin->ActionDoGroup($arRes["ID"], "move") ); } else { $arActions[] = array( "TEXT"=>GetMessage("CLO_STORAGE_LIST_START_MOVE_FILES"), "ACTION"=>$lAdmin->ActionDoGroup($arRes["ID"], "move") ); } } if($bHasLocalStorage) { $arActions[] = array( "TEXT"=>GetMessage("CLO_STORAGE_LIST_MOVE_LOCAL"), "ACTION"=>"if(confirm('".GetMessage("CLO_STORAGE_LIST_MOVE_LOCAL_CONF")."')) ".$lAdmin->ActionDoGroup($arRes["ID"], "download") ); } $arActions[] = array( "TEXT"=>GetMessage("CLO_STORAGE_LIST_DEACTIVATE"), "ACTION"=>"if(confirm('".GetMessage("CLO_STORAGE_LIST_DEACTIVATE_CONF")."')) ".$lAdmin->ActionDoGroup($arRes["ID"], "deactivate") ); } else { $arActions[] = array( "TEXT"=>GetMessage("CLO_STORAGE_LIST_ACTIVATE"), "ACTION"=>$lAdmin->ActionDoGroup($arRes["ID"], "activate") ); } if(intval($arRes["B_FILE_COUNT"]) > 0) { $arActions[] = array( "ICON"=>"delete", "TEXT"=>GetMessage("CLO_STORAGE_LIST_DELETE"), "ACTION"=>"alert('".GetMessage("CLO_STORAGE_LIST_CANNOT_DELETE")."')" ); } else { $arActions[] = array( "ICON"=>"delete", "TEXT"=>GetMessage("CLO_STORAGE_LIST_DELETE"), "ACTION"=>"if(confirm('".GetMessage("CLO_STORAGE_LIST_DELETE_CONF")."')) ".$lAdmin->ActionDoGroup($arRes["ID"], "delete") ); } if(!empty($arActions) && !$bOnTheMove) $row->AddActions($arActions); } $arFooter = array( array( "title" => GetMessage("MAIN_ADMIN_LIST_SELECTED"), "value" => $rsData->SelectedRowsCount(), ), array( "counter" => true, "title" => GetMessage("MAIN_ADMIN_LIST_CHECKED"), "value" => 0, ), ); $lAdmin->AddFooter($arFooter); $aContext = array( array( "TEXT" => GetMessage("CLO_STORAGE_LIST_ADD"), "LINK" => "/bitrix/admin/clouds_storage_edit.php?lang=".LANGUAGE_ID, "TITLE" => GetMessage("CLO_STORAGE_LIST_ADD_TITLE"), "ICON" => "btn_new", ), ); $lAdmin->AddAdminContextMenu($aContext, /*$bShowExcel=*/false); $lAdmin->CheckListMode(); $APPLICATION->SetTitle(GetMessage("CLO_STORAGE_LIST_TITLE")); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php"); $lAdmin->DisplayList(); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php"); ?>admin/clouds_file_list.php000064400000065137150241560060011703 0ustar00<? define("ADMIN_MODULE_NAME", "clouds"); /*.require_module 'standard';.*/ /*.require_module 'pcre';.*/ /*.require_module 'bitrix_main_include_prolog_admin_before';.*/ require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php"); if(!$USER->CanDoOperation("clouds_browse")) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); /*.require_module 'bitrix_clouds_include';.*/ if(!CModule::IncludeModule('clouds')) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); IncludeModuleLangFile(__FILE__); $obBucket = new CCloudStorageBucket(intval($_GET["bucket"])); if(!$obBucket->Init()) { $APPLICATION->SetTitle($obBucket->BUCKET); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php"); $message = new CAdminMessage(array( "MESSAGE" => GetMessage("CLO_STORAGE_FILE_LIST_ERROR"), "DETAILS" => GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "L00")), )); echo $message->Show(); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php"); die(); } $PHPchunkSize = 1024*1024; // 1M later TODO return_bytes(ini_get('post_max_size')) $CLOchunkSize = $obBucket->GetService()->GetMinUploadPartSize(); $message = /*.(CAdminMessage).*/null; $path = (string)$_GET["path"]; $sTableID = "tbl_clouds_file_list"; $lAdmin = new CAdminList($sTableID); $arFilterFields = Array( "find_name", ); $lAdmin->InitFilter($arFilterFields); $arID = $lAdmin->GroupAction(); $action = isset($_REQUEST["action"]) && is_string($_REQUEST["action"])? "$_REQUEST[action]": ""; if($USER->CanDoOperation("clouds_upload") && is_array($arID)) { foreach($arID as $ID) { if(strlen($ID) <= 0) continue; $ID = urldecode($ID); switch($action) { case "delete": if(substr($ID, 0, 1) === "F") { $file_size = $obBucket->GetFileSize($path.substr($ID, 1)); if(!$obBucket->DeleteFile($path.substr($ID, 1))) { $e = $APPLICATION->GetException(); if(is_object($e)) $lAdmin->AddUpdateError($e->GetString(), $ID); else $lAdmin->AddUpdateError(GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array( "#CODE#" => "D01", )), $ID); } else { $obBucket->DecFileCounter($file_size); } } elseif(substr($ID, 0, 1) === "D") { $arFiles = $obBucket->ListFiles($path.substr($ID, 1), true); foreach($arFiles["file"] as $i => $file) { if(!$obBucket->DeleteFile($path.substr($ID, 1)."/".$file)) { $e = $APPLICATION->GetException(); if(is_object($e)) $lAdmin->AddUpdateError($e->GetString(), $ID); else $lAdmin->AddUpdateError(GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array( "#CODE#" => "D02", )), $ID); break; } else { $obBucket->DecFileCounter($arFiles["file_size"][$i]); } } } break; case "chunk_upload": require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_js.php"); $strError = ""; $bytes = 0; $fileSize = doubleval($_REQUEST["file_size"]); $tempDir = CTempFile::GetDirectoryName(6, "clouds_ipload"); $absPath = $tempDir."tmp_name"; if(isset($_REQUEST["file_name"])) { $filePath = $_REQUEST["file_name"]; $filePath = "/".$_REQUEST["path_to_upload"]."/".$filePath; $filePath = preg_replace("#[\\\\\\/]+#", "/", $filePath); if (isset($_REQUEST["chunk_start"]) && $_REQUEST["chunk_start"] == 0) { if($obBucket->FileExists($filePath)) $strError = GetMessage("CLO_STORAGE_FILE_EXISTS_ERROR"); } } if(isset($_REQUEST["chunk_start"])) { CheckDirPath($tempDir); // read contents from the input stream $inputHandler = fopen('php://input', "rb"); // create a temp file where to save data from the input stream $fileHandler = fopen($absPath, "ab"); // save data from the input stream while(!feof($inputHandler)) fwrite($fileHandler, fread($inputHandler, 1024*1024)); fclose($fileHandler); } else { @unlink($absPath); } if($strError == "") { if($fileSize <= $CLOchunkSize) { if(!file_exists($absPath)) { $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; ?><script> readFileChunk(0, <?echo $PHPchunkSize-1?>); </script><? } elseif(filesize($absPath) < $fileSize) { $bytes = filesize($absPath); $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; ?><script> readFileChunk(<?echo $bytes?>, <?echo min($fileSize-1, $bytes+$PHPchunkSize-1)?>); </script><? } else { $ar = CFile::MakeFileArray($absPath); if(!is_array($ar) || !isset($ar["tmp_name"])) { $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e11")); } else { $res = $obBucket->SaveFile($filePath, $ar); if($res) { $bytes = $fileSize; $moveResult = CCloudStorage::FILE_MOVED; $obBucket->IncFileCounter($fileSize); } else { $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e12")); } @unlink($absPath); } } } else { $obUpload = new CCloudStorageUpload($filePath); if(!$obUpload->isStarted()) { if($obUpload->Start($obBucket->ID, $fileSize, $_REQUEST["file_type"])) { $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; ?><script> readFileChunk(0, <?echo $PHPchunkSize-1?>); </script><? } else $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e01")); } else { $pos = $obUpload->getPos(); if($pos > $fileSize) { if($obUpload->Finish()) { $bytes = $fileSize; $obBucket->IncFileCounter($fileSize); @unlink($absPath); $moveResult = CCloudStorage::FILE_MOVED; } else { $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e02")); } } else { if(!file_exists($absPath)) { $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; ?><script> readFileChunk(<?echo $pos?>, <?echo $pos + $PHPchunkSize-1?>); </script><? } elseif( filesize($absPath) < $obUpload->getPartSize() && ($pos + filesize($absPath) < $fileSize) ) { $bytes = $pos + filesize($absPath); $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; ?><script> readFileChunk(<?echo $bytes?>, <?echo min($fileSize-1, $bytes+$PHPchunkSize-1)?>); </script><? } else { $part = file_get_contents($absPath); $bytes = $pos + filesize($absPath); $moveResult = CCloudStorage::FILE_SKIPPED; while($obUpload->hasRetries()) { if($obUpload->Next($part)) { $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; break; } } if($moveResult == CCloudStorage::FILE_SKIPPED) $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e03")); else { ?><script> readFileChunk(<?echo $obUpload->getPos()?>, <?echo min($fileSize-1, $obUpload->getPos()+$PHPchunkSize-1)?>); </script><? @unlink($absPath); } } } } } } if($strError != "") { $e = $APPLICATION->GetException(); if(!is_object($e)) $e = new CApplicationException($strError); $message = new CAdminMessage(GetMessage("CLO_STORAGE_FILE_UPLOAD_ERROR"), $e); } if(is_object($message)) { echo $message->Show(); $message = null; } elseif($moveResult == CCloudStorage::FILE_PARTLY_UPLOADED) { CAdminMessage::ShowMessage(array( "TYPE"=>"PROGRESS", "MESSAGE"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_IN_PROGRESS"), "DETAILS"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_PROGRESS", array( "#bytes#" => CFile::FormatSize($bytes), "#file_size#" => CFile::FormatSize($fileSize), ))."#PROGRESS_BAR#", "HTML"=>true, "PROGRESS_TOTAL" => $fileSize, "PROGRESS_VALUE" => $bytes, "BUTTONS" => array( array( "VALUE" => GetMessage("CLO_STORAGE_FILE_STOP"), "ONCLICK" => 'window.location = \''.CUtil::AddSlashes("/bitrix/admin/clouds_file_list.php?lang=".urlencode(LANGUAGE_ID)."&bucket=".urlencode($obBucket->ID)."&path=".urlencode($path)).'\'', ), ), )); } else { CAdminMessage::ShowMessage(array( "MESSAGE"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_DONE"), "DETAILS"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_PROGRESS", array( "#bytes#" => CFile::FormatSize($bytes), "#file_size#" => CFile::FormatSize($fileSize), )), "HTML"=>true, "TYPE"=>"OK", )); ?><script> <?=$sTableID?>.GetAdminList('<?echo CUtil::JSEscape($APPLICATION->GetCurPage().'?lang='.urlencode(LANGUAGE_ID).'&bucket='.urlencode($obBucket->ID).'&path='.urlencode($path))?>'); </script><? } require($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/main/include/epilog_admin_js.php"); case "upload": $strError = ""; $io = CBXVirtualIo::GetInstance(); $f = null; if($ID === "Fnew" && isset($_FILES["upload"])) { if($_FILES["upload"]["error"] == 0) { $filePath = $_FILES["upload"]["name"]; $filePath = "/".$_REQUEST["path_to_upload"]."/".$filePath; $filePath = preg_replace("#[\\\\\\/]+#", "/", $filePath); $f = $io->GetFile($_FILES["upload"]["tmp_name"]); } else { $message = new CAdminMessage(GetMessage("CLO_STORAGE_FILE_UPLOAD_ERROR"), new CApplicationException(GetMessage("CLO_STORAGE_FILE_OPEN_ERROR"))); } } elseif($ID !== "Fnew") { //TODO check for ../../../ $filePath = substr($ID, 1); $filePath = "/".$path."/".$filePath; $filePath = preg_replace("#[\\\\\\/]+#", "/", $filePath); $f = $io->GetFile(preg_replace("#[\\\\\\/]+#", "/", $_SERVER["DOCUMENT_ROOT"]."/".$path."/".substr($ID, 1))); } elseif(isset($_REQUEST["filePath"])) { $obUpload = new CCloudStorageUpload($_REQUEST["filePath"]); if($obUpload->isStarted()) { $tempFile = $obUpload->getTempFileName(); if($tempFile) $f = $io->GetFile($tempFile); } } if(!$f) break; if( substr($ID, 0, 1) !== "F" || $obBucket->ACTIVE !== "Y" || $obBucket->READ_ONLY !== "N" ) break; $fp = $f->Open("rb"); if(!is_resource($fp)) { $message = new CAdminMessage(GetMessage("CLO_STORAGE_FILE_UPLOAD_ERROR"), new CApplicationException(GetMessage("CLO_STORAGE_FILE_OPEN_ERROR"))); break; } $bytes = 0; $fileSize = $f->GetFileSize(); if($fileSize > $obBucket->GetService()->GetMinUploadPartSize()) { $obUpload = new CCloudStorageUpload($filePath); if(!$obUpload->isStarted()) { if($obBucket->FileExists($filePath)) { $message = new CAdminMessage(GetMessage("CLO_STORAGE_FILE_UPLOAD_ERROR"), new CApplicationException(GetMessage("CLO_STORAGE_FILE_EXISTS_ERROR"))); break; } $tempFile = CTempFile::GetDirectoryName(6, "clouds_upload").$f->GetName(); $tempFileX = $io->GetPhysicalName($tempFile); CheckDirPath($tempFileX); if(copy($io->GetPhysicalName($f->GetPathWithName()), $tempFileX)) { if($obUpload->Start($obBucket->ID, $fileSize, CFile::GetContentType($tempFile), $tempFile)) $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; else $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e01")); } else { $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e04")); } } else { $pos = $obUpload->getPos(); if($pos > $fileSize) { if($obUpload->Finish()) { $bytes = $fileSize; $obBucket->IncFileCounter($fileSize); @unlink($io->GetPhysicalName($f->GetPathWithName())); $moveResult = CCloudStorage::FILE_MOVED; } else { $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e02")); } } else { fseek($fp, $pos); $part = fread($fp, $obUpload->getPartSize()); $bytes = $pos + $part; $moveResult = CCloudStorage::FILE_SKIPPED; while($obUpload->hasRetries()) { if($obUpload->Next($part)) { $moveResult = CCloudStorage::FILE_PARTLY_UPLOADED; break; } } if($moveResult == CCloudStorage::FILE_SKIPPED) $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e03")); } } } else { if($obBucket->FileExists($filePath)) { $message = new CAdminMessage(GetMessage("CLO_STORAGE_FILE_UPLOAD_ERROR"), new CApplicationException(GetMessage("CLO_STORAGE_FILE_EXISTS_ERROR"))); break; } $ar = CFile::MakeFileArray($io->GetPhysicalName($f->GetPathWithName())); if(!is_array($ar) || !isset($ar["tmp_name"])) { $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e11")); } else { $res = $obBucket->SaveFile($filePath, $ar); if($res) { $bytes = $fileSize; $moveResult = CCloudStorage::FILE_MOVED; $obBucket->IncFileCounter($fileSize); @unlink($io->GetPhysicalName($f->GetPathWithName())); } else { $strError = GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "e12")); } } } $lAdmin->BeginPrologContent(); if($strError != "") { $e = $APPLICATION->GetException(); if(!is_object($e)) $e = new CApplicationException($strError); $message = new CAdminMessage(GetMessage("CLO_STORAGE_FILE_UPLOAD_ERROR"), $e); } if(is_object($message)) { echo $message->Show(); $message = null; } elseif($moveResult == CCloudStorage::FILE_PARTLY_UPLOADED) { CAdminMessage::ShowMessage(array( "MESSAGE"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_IN_PROGRESS"), "DETAILS"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_PROGRESS", array( "#bytes#" => CFile::FormatSize($bytes), "#file_size#" => CFile::FormatSize($fileSize), )).'#PROGRESS_BAR#', "HTML"=>true, "TYPE"=>"PROGRESS", "PROGRESS_TOTAL" => $fileSize, "PROGRESS_VALUE" => $bytes, "BUTTONS" => array( array( "VALUE" => GetMessage("CLO_STORAGE_FILE_STOP"), "ONCLICK" => 'window.location = \''.CUtil::JSEscape("/bitrix/admin/clouds_file_list.php?lang=".urlencode(LANGUAGE_ID)."&bucket=".urlencode($obBucket->ID)."&path=".urlencode($path)).'\'', ), ), )); } else { CAdminMessage::ShowMessage(array( "MESSAGE"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_DONE"), "DETAILS"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_PROGRESS", array( "#bytes#" => CFile::FormatSize($bytes), "#file_size#" => CFile::FormatSize($fileSize), )), "HTML"=>true, "TYPE"=>"OK", )); } $lAdmin->EndPrologContent(); if($moveResult == CCloudStorage::FILE_PARTLY_UPLOADED) { $lAdmin->BeginEpilogContent(); echo '<script>BX.ready(function(){', $lAdmin->ActionDoGroup(urlencode($ID), "upload", "bucket=".urlencode($obBucket->ID)."&path=".urlencode($path)."&filePath=".urlencode($filePath)), '});</script>'; $lAdmin->EndEpilogContent(); } break; default: break; } } } $arHeaders = array( array( "id" => "FILE_NAME", "content" => GetMessage("CLO_STORAGE_FILE_NAME"), "default" => true, ), array( "id" => "FILE_SIZE", "content" => GetMessage("CLO_STORAGE_FILE_SIZE"), "align" => "right", "default" => true, ), ); $lAdmin->AddHeaders($arHeaders); $arData = /*.(array[int][string]string).*/array(); $arFiles = $obBucket->ListFiles($path); if($path != "/") { $arData[] = array( "ID" => "D..", "TYPE" => "dir", "NAME" => "..", "SIZE" => "", ); } if(is_array($arFiles)) { foreach($arFiles["dir"] as $i => $dir) { if ($find_name == "" || strpos($dir, $find_name) !== false) { $arData[] = array( "ID" => "D".urlencode($dir), "TYPE" => "dir", "NAME" => $dir, "SIZE" => '', ); } } foreach($arFiles["file"] as $i => $file) { if ($find_name == "" || strpos($file, $find_name) !== false) { $arData[] = array( "ID" => "F".urlencode($file), "TYPE" => "file", "NAME" => $file, "SIZE" => $arFiles["file_size"][$i], ); } } } else { $e = $APPLICATION->GetException(); if(is_object($e)) $message = new CAdminMessage(GetMessage("CLO_STORAGE_FILE_LIST_ERROR"), $e); else $message = new CAdminMessage(array( "MESSAGE" => GetMessage("CLO_STORAGE_FILE_LIST_ERROR"), "DETAILS" => GetMessage("CLO_STORAGE_FILE_UNKNOWN_ERROR", array("#CODE#" => "L01")), )); } $total_size = 0.0; $total_count = 0; $rsData = new CDBResult; $rsData->InitFromArray($arData); $rsData = new CAdminResult($rsData, $sTableID); $rsData->NavStart(); $lAdmin->NavText($rsData->GetNavPrint('')); while(is_array($arRes = $rsData->NavNext())) { $row =& $lAdmin->AddRow($arRes["ID"], $arRes); if($arRes["TYPE"] === "dir") { if($arRes["NAME"] === "..") { $row->bReadOnly = true; $row->AddViewField("FILE_NAME", '<a href="'.htmlspecialcharsbx('clouds_file_list.php?lang='.urlencode(LANGUAGE_ID).'&bucket='.urlencode($obBucket->ID).'&path='.urlencode(preg_replace('#([^/]+)/$#', '', $path))).'" class="adm-list-table-icon-link"><span class="adm-submenu-item-link-icon adm-list-table-icon clouds-up-icon"></span><span class="adm-list-table-link">'.htmlspecialcharsex($arRes["NAME"]).'</span></a>'); $row->AddViewField("FILE_SIZE", ' '); } else { $row->AddViewField("FILE_NAME", '<a href="'.htmlspecialcharsbx('clouds_file_list.php?lang='.urlencode(LANGUAGE_ID).'&bucket='.urlencode($obBucket->ID).'&path='.urlencode($path.$arRes["NAME"].'/')).'" class="adm-list-table-icon-link"><span class="adm-submenu-item-link-icon adm-list-table-icon clouds-directory-icon"></span><span class="adm-list-table-link">'.htmlspecialcharsex($arRes["NAME"]).'</span></a>'); if($_GET["size"] === "y") { $arDirFiles = $obBucket->ListFiles($path.$arRes["NAME"]."/", true); $size = array_sum($arDirFiles["file_size"]); $row->AddViewField("FILE_SIZE", CFile::FormatSize((float)$size)); $total_size += $size; $total_count += count($arDirFiles["file"]); } else { $row->AddViewField("FILE_SIZE", ' '); } } } else { $row->AddViewField("FILE_NAME", '<a href="'.htmlspecialcharsbx($obBucket->GetFileSRC(array("URN" => $path.$arRes["NAME"]))).'">'.htmlspecialcharsex($arRes["NAME"]).'</a>'); $row->AddViewField("FILE_SIZE", CFile::FormatSize((float)$arRes["SIZE"])); $total_size += $arRes["SIZE"]; $total_count++; } $arActions = /*.(array[int][string]string).*/array(); if($USER->CanDoOperation("clouds_upload")) $arActions[] = array( "ICON"=>"delete", "TEXT"=>GetMessage("CLO_STORAGE_FILE_DELETE"), "ACTION"=>"if(confirm('".GetMessage("CLO_STORAGE_FILE_DELETE_CONF")."')) ".$lAdmin->ActionDoGroup($arRes["ID"], "delete", 'bucket='.urlencode($obBucket->ID).'&path='.urlencode($path)) ); if(!empty($arActions)) $row->AddActions($arActions); } if( ($_GET["size"] === "y") && is_array($arFiles) && ( (round($total_size/1024) != round($obBucket->FILE_SIZE/1024)) || ($total_count != $obBucket->FILE_COUNT) ) ) { $obBucket->SetFileCounter($total_size, $total_count); } $arFooter = array( array( "title" => GetMessage("MAIN_ADMIN_LIST_SELECTED"), "value" => $path === "/"? $rsData->SelectedRowsCount(): $rsData->SelectedRowsCount()-1, // W/O .. ), array( "title" => GetMessage("MAIN_ADMIN_LIST_CHECKED"), "value" => 0, "counter" => true, ), ); if($total_size > 0) { $arFooter[] = array( "title" => GetMessage("CLO_STORAGE_FILE_SIZE").":", "value" => CFile::FormatSize($total_size), ); } $lAdmin->AddFooter($arFooter); $arGroupActions = array(); if($USER->CanDoOperation("clouds_upload")) $arGroupActions["delete"] = GetMessage("MAIN_ADMIN_LIST_DELETE"); $lAdmin->AddGroupActionTable($arGroupActions); $chain = $lAdmin->CreateChain(); $arPath = explode("/", $path); $curPath = "/"; foreach($arPath as $dir) { if($dir != "") { $curPath .= $dir."/"; $url = "clouds_file_list.php?lang=".urlencode(LANGUAGE_ID)."&bucket=".urlencode($obBucket->ID)."&path=".urlencode($curPath); $chain->AddItem(array( "TEXT" => htmlspecialcharsex($dir), "LINK" => htmlspecialcharsbx($url), "ONCLICK" => $lAdmin->ActionAjaxReload($url).';return false;', )); } } $lAdmin->ShowChain($chain); $aContext = array(); if( $obBucket->ACTIVE === "Y" && $obBucket->READ_ONLY === "N" && $USER->CanDoOperation("clouds_upload") ) { $aContext[] = array( "TEXT" => GetMessage("CLO_STORAGE_FILE_UPLOAD"), "LINK" => "javascript:show_upload_form()", "TITLE" => GetMessage("CLO_STORAGE_FILE_UPLOAD_TITLE"), "ICON" => "btn_new", ); } $aContext[] = array( "TEXT" => GetMessage("CLO_STORAGE_FILE_SHOW_DIR_SIZE"), "LINK" => "/bitrix/admin/clouds_file_list.php?lang=".urlencode(LANGUAGE_ID).'&bucket='.urlencode($obBucket->ID).'&path='.urlencode($path).'&size=y', "TITLE" => GetMessage("CLO_STORAGE_FILE_SHOW_DIR_SIZE_TITLE"), ); $lAdmin->AddAdminContextMenu($aContext, /*$bShowExcel=*/false); $lAdmin->BeginPrologContent(); if(is_object($message)) echo $message->Show(); $lAdmin->EndPrologContent(); $lAdmin->CheckListMode(); $APPLICATION->SetTitle($obBucket->BUCKET); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php"); if($USER->CanDoOperation("clouds_upload")): CUtil::InitJSCore(array('fx')); $aTabs = array( array( "DIV" => "edit1", "TAB" => GetMessage("CLO_STORAGE_FILE_UPLOAD"), "ICON"=>"main_user_edit", "TITLE"=>GetMessage("CLO_STORAGE_FILE_UPLOAD_TITLE"), ), ); $tabControl = new CAdminTabControl("tabControl", $aTabs, true, true); ?> <form name="find_form" method="GET" action="<?echo $APPLICATION->GetCurPage()?>?"> <? $oFilter = new CAdminFilter( $sTableID."_filter", array( ) ); $oFilter->Begin(); ?> <tr> <td><b><?= GetMessage("CLO_STORAGE_FILE_NAME")?>:</b></td> <td nowrap> <input type="text" name="find_name" value="<?= htmlspecialcharsbx($find_name)?>" size="35"> </td> </tr> <? $oFilter->Buttons(array( "table_id"=>$sTableID, "url"=>"/bitrix/admin/clouds_file_list.php?lang=".urlencode(LANGUAGE_ID).'&bucket='.urlencode($obBucket->ID).'&path='.urlencode($path), "form"=>"find_form", )); $oFilter->End(); ?> </form> <script> function show_upload_form() { (new BX.fx({ start: 0, finish: 200, time: 0.5, type: 'accelerated', callback: function(res){ BX('upload_form', true).style.height = res+'px'; }, callback_start: function(){ BX('upload_form', true).style.height = '0px'; BX('upload_form', true).style.overflow = 'hidden'; BX('upload_form', true).style.display = 'block'; }, callback_complete: function(){ BX('upload_form', true).style.height = 'auto'; BX('upload_form', true).style.overflow = 'auto'; } })).start(); } function hide_upload_form() { BX('upload_form').style.display='none'; return; } function get_upload_url(additional_args) { var result = 'clouds_file_list.php?' + 'action=chunk_upload' + '&ID=Fnew' + '&lang=<?echo urlencode(LANGUAGE_ID)?>' + '&path=<?echo urlencode($path)?>' + '&path_to_upload=' + BX('path_to_upload').value + '&<?echo bitrix_sessid_get()?>' + '&bucket=<?echo CUtil::JSEscape($obBucket->ID)?>' ; if(additional_args) { for(x in additional_args) result += '&' + x + '=' + BX.util.urlencode(additional_args[x]); } return result; } function chunk_upload(opt_Chunk, file, opt_startByte) { var data = new ArrayBuffer(opt_Chunk.length); var ui8a = new Uint8Array(data, 0); for (var i = 0; i < opt_Chunk.length; i++) ui8a[i] = (opt_Chunk.charCodeAt(i) & 0xff); var blob; try { blob = new Blob([ui8a]); } catch (e) { var bb = new (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)(); bb.append(data); blob = bb.getBlob(); } ShowWaitWindow(); BX.ajax({ 'method': 'POST', 'dataType': 'html', 'url': get_upload_url({ file_name: file.name, file_size: file.size, file_type: file.type, chunk_start: opt_startByte }), 'data': blob, 'onsuccess': function(result){ BX('upload_progress').innerHTML = result; var href = BX('stop_button'); if(!href) { CloseWaitWindow(); BX('start_upload_button').enabled = true; } }, 'preparePost': false }); } function start_upload() { if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { BX('editform').submit(); return; } var files = BX('upload').files; if (!files || !files.length) return; var file = files[0]; ShowWaitWindow(); BX('start_upload_button').enabled = false; BX.ajax.post( get_upload_url({ file_name: file.name, file_size: file.size, file_type: file.type }), {}, function(result){ BX('upload_progress').innerHTML = result; var href = BX('stop_button'); if(!href) { CloseWaitWindow(); BX('start_upload_button').disabled = false; } } ); } function readFileChunk(opt_startByte, opt_stopByte) { var files = BX('upload').files; if (!files || !files.length) return; var file = files[0]; var start = parseInt(opt_startByte) || 0; var stop = parseInt(opt_stopByte) || file.size - 1; var reader = new FileReader(); reader.onloadend = function(evt) { if (evt.target.readyState == FileReader.DONE) chunk_upload(evt.target.result, file, start); }; if (file.webkitSlice) //Deprecated var blob = file.webkitSlice(start, stop + 1); else if (file.mozSlice) //Deprecated var blob = file.mozSlice(start, stop + 1); else if (file.slice) var blob = file.slice(start, stop + 1); reader.readAsBinaryString(blob); } </script> <div id="upload_form" style="display:none;height:200px;"> <div id="upload_progress"></div> <form method="POST" action="<?echo htmlspecialcharsbx($APPLICATION->GetCurPageParam())?>" enctype="multipart/form-data" name="editform" id="editform"> <? $tabControl->Begin(); $tabControl->BeginNextTab(); ?> <tr><td width="40%"><?echo GetMessage("CLO_STORAGE_FILE_PATH_INPUT")?>:</td><td width="60%"><input type="text" id="path_to_upload" name="path_to_upload" size="45" value="<?echo htmlspecialcharsbx($path)?>"></td></tr> <tr><td><?echo GetMessage("CLO_STORAGE_FILE_UPLOAD_INPUT")?>:</td><td><input type="file" id="upload" name="upload"></td></tr> <?$tabControl->Buttons(false);?> <input type="hidden" name="action" value="upload"> <input type="hidden" name="ID" value="Fnew"> <?echo bitrix_sessid_post();?> <input type="hidden" name="lang" value="<?echo LANGUAGE_ID?>"> <input type="button" id="start_upload_button" onclick="start_upload();" value="<?echo GetMessage("CLO_STORAGE_FILE_UPLOAD_BTN")?>" class="adm-btn-save"> <input type="button" value="<?echo GetMessage("CLO_STORAGE_FILE_CANCEL_BTN")?>" onclick="hide_upload_form()"> <? $tabControl->End(); ?> </form> </div> <? endif; $lAdmin->DisplayList(); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php"); ?>admin/clouds_storage_edit.php000064400000030662150241560060012375 0ustar00<? define("ADMIN_MODULE_NAME", "clouds"); /*.require_module 'standard';.*/ /*.require_module 'hash';.*/ /*.require_module 'bitrix_main_include_prolog_admin_before';.*/ require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php"); if(!$USER->CanDoOperation("clouds_config")) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); /*.require_module 'bitrix_clouds_include';.*/ if(!CModule::IncludeModule('clouds')) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); IncludeModuleLangFile(__FILE__); $aTabs = array( array( "DIV" => "edit1", "TAB" => GetMessage("CLO_STORAGE_EDIT_TAB"), "ICON"=>"main_user_edit", "TITLE"=>GetMessage("CLO_STORAGE_EDIT_TAB_TITLE"), ), array( "DIV" => "edit2", "TAB" => GetMessage("CLO_STORAGE_EDIT_TAB2"), "ICON"=>"main_user_edit", "TITLE"=>GetMessage("CLO_STORAGE_EDIT_TAB2_TITLE"), ), ); $tabControl = new CAdminTabControl("tabControl", $aTabs); $ID = intval($_REQUEST["ID"]); // Id of the edited record $bVarsFromForm = false; $message = /*.(CAdminMessage).*/null; if($_SERVER["REQUEST_METHOD"] === "POST" && check_bitrix_sessid()) { if(isset($_REQUEST["save"]) || isset($_REQUEST["apply"])) { $ob = new CCloudStorageBucket($ID); $arFields = array( "ACTIVE" => $_POST["ACTIVE"] === "Y"? "Y": "N", "READ_ONLY" => $_POST["READ_ONLY"] === "Y"? "Y": "N", "SORT" => $_POST["SORT"], "SERVICE_ID" => $_POST["SERVICE_ID"], "BUCKET" => $_POST["BUCKET"], "LOCATION" => $_POST["LOCATION"][$_POST["SERVICE_ID"]], "SETTINGS" => $_POST["SETTINGS"][$_POST["SERVICE_ID"]], "CNAME" => $_POST["CNAME"], "FILE_RULES" => CCloudStorageBucket::ConvertPOST($_POST), ); if($ID > 0) $res = $ob->Update($arFields); else $res = $ob->Add($arFields); if($res > 0) { if(isset($_REQUEST["apply"])) LocalRedirect("/bitrix/admin/clouds_storage_edit.php?ID=".$res."&lang=".LANGUAGE_ID."&".$tabControl->ActiveTabParam()); else LocalRedirect("/bitrix/admin/clouds_storage_list.php?lang=".LANGUAGE_ID); } else { $e = $APPLICATION->GetException(); if(is_object($e)) $message = new CAdminMessage(GetMessage("CLO_STORAGE_EDIT_SAVE_ERROR"), $e); $bVarsFromForm = true; } } elseif(isset($_REQUEST["delete"]) && $ID > 1) { $ob = new CCloudStorageBucket($ID); if($ob->Delete()) LocalRedirect("/bitrix/admin/clouds_storage_list.php?lang=".LANGUAGE_ID); else $bVarsFromForm = true; } } if($bVarsFromForm) { $arRes = array( "ACTIVE" => (string)$_REQUEST["ACTIVE"], "SORT" => "500", "READ_ONLY" => (string)$_REQUEST["READ_ONLY"], "SERVICE_ID" => (string)$_REQUEST["SERVICE_ID"], "BUCKET" => (string)$_REQUEST["BUCKET"], "LOCATION" => (string)$_REQUEST["LOCATION"], "CNAME" => (string)$_REQUEST["CNAME"], "SETTINGS" => "", ); if(isset($_REQUEST["SETTINGS"]) && is_array($_REQUEST["SETTINGS"])) $arRes["SETTINGS"] = $_REQUEST["SETTINGS"]; } else { $arRes = null; if($ID > 0) { $rs = CCloudStorageBucket::GetList(array("ID" => "ASC"), array("=ID" => $ID)); $arRes = $rs->Fetch(); } if(!is_array($arRes)) { $ID = 0; $arRes = array( "ACTIVE" => "Y", "SORT" => "500", "READ_ONLY" => "N", "SERVICE_ID" => "", "BUCKET" => "upload-".md5(uniqid("", true)), "LOCATION" => "", "CNAME" => "", "SETTINGS" => "", ); } } $APPLICATION->SetTitle(($ID > 0? GetMessage("CLO_STORAGE_EDIT_EDIT_TITLE") : GetMessage("CLO_STORAGE_EDIT_ADD_TITLE"))); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php"); $aMenu = array( array( "TEXT" => GetMessage("CLO_STORAGE_EDIT_MENU_LIST"), "TITLE" => GetMessage("CLO_STORAGE_EDIT_MENU_LIST_TITLE"), "LINK" => "clouds_storage_list.php?lang=".LANGUAGE_ID, "ICON" => "btn_list", ) ); $context = new CAdminContextMenu($aMenu); $context->Show(); if(is_object($message)) echo $message->Show(); ?> <script> function ChangeLocation(select) { var trs; trs = BX.findChildren(BX('editform'), {'tag':'tr','class':'location-tr'}, true); for(var i = 0;i < trs.length; i++) trs[i].style.display = 'none'; trs = BX.findChildren(BX('editform'), {'tag':'tr','class':'settings-tr'}, true); for(var i = 0;i < trs.length; i++) trs[i].style.display = 'none'; BX('LOCATION_' + select.value).style.display = ''; var i = 0; while(true) { var tr = BX('SETTINGS_' + i + '_' + select.value); if(tr) { tr.style.display = ''; } else { break; } i++; } } function editAddRule() { var tbl = BX('tblRULES'); var oRow = tbl.insertRow(-1); var oCell1 = oRow.insertCell(0); oCell1.innerHTML = '<input name="MODULE[]" type="text" style="width:100%">'; var oCell2 = oRow.insertCell(1); oCell2.innerHTML = '<input name="EXTENSION[]" type="text" style="width:100%">'; var oCell3 = oRow.insertCell(2); oCell3.innerHTML = '<input name="SIZE[]" type="text" style="width:100%">'; var oCell4 = oRow.insertCell(3); oCell4.innerHTML = '<img src="/bitrix/themes/.default/images/actions/delete_button.gif" onclick="editDeleteRule(this) "/>'; if (document.forms.editform.BXAUTOSAVE) { setTimeout(function() { var r = BX.findChildren(oRow, {tag: 'input'}, true); if (r && r.length > 0) { for (var i=0,l=r.length;i<l;i++) { r[i].form.BXAUTOSAVE.RegisterInput(r[i]); } } }, 10); } } function editDeleteRule(img) { var oTR = BX.findParent(img, {tag: 'tr'}); oTR.parentNode.removeChild(oTR); } </script> <form method="POST" action="<?echo $APPLICATION->GetCurPage()?>" enctype="multipart/form-data" name="editform" id="editform"> <? $tabControl->Begin(); ?> <? $tabControl->BeginNextTab(); ?> <?if($ID > 0) {?> <tr> <td><?echo GetMessage("CLO_STORAGE_EDIT_ID")?>:</td> <td><?echo $ID;?></td> </tr> <?}?> <tr> <td width="40%"><?echo GetMessage("CLO_STORAGE_EDIT_ACTIVE")?>:</td> <td width="60%"><input type="hidden" name="ACTIVE" value="N"><input type="checkbox" name="ACTIVE" value="Y"<?if($arRes["ACTIVE"] === "Y") echo " checked"?>></td> </tr> <tr> <td><?echo GetMessage("CLO_STORAGE_EDIT_SORT")?>:</td> <td><input type="text" size="6" name="SORT" value="<?echo intval($arRes["SORT"])?>"></td> </tr> <?if($ID > 0) {?> <tr> <td><?echo GetMessage("CLO_STORAGE_EDIT_SERVICE_ID")?>:</td> <td> <? $obService = /*.(CCloudStorageService).*/null; foreach(CCloudStorage::GetServiceList() as $SERVICE_ID => $obService) { if($arRes["SERVICE_ID"] === $SERVICE_ID) { echo htmlspecialcharsex($obService->GetName()); break; } } ?> <input type="hidden" name="SERVICE_ID" value="<?echo htmlspecialcharsbx($arRes["SERVICE_ID"]);?>"> </td> </tr> <tr id="LOCATION_<?echo htmlspecialcharsbx($arRes["SERVICE_ID"])?>" class="location-tr"> <td><?echo GetMessage("CLO_STORAGE_EDIT_LOCATION")?>:</td> <td> <? foreach(CCloudStorage::GetServiceLocationList($arRes["SERVICE_ID"]) as $LOCATION_ID => $LOCATION_NAME) { if($arRes["LOCATION"] == $LOCATION_ID) echo htmlspecialcharsex($LOCATION_NAME); } ?> <input type="hidden" name="LOCATION[<?echo htmlspecialcharsbx($arRes["SERVICE_ID"]);?>]" value="<?echo htmlspecialcharsbx($arRes["LOCATION"]);?>"> </td> </tr> <?if(is_object($obService)) echo $obService->GetSettingsHTML($arRes, true, $arRes["SERVICE_ID"], $bVarsFromForm);?> <?} else {?> <tr> <td><?echo GetMessage("CLO_STORAGE_EDIT_SERVICE_ID")?>:</td> <td> <select name="SERVICE_ID" onchange="ChangeLocation(this)"> <? $bServiceSet = false; foreach(CCloudStorage::GetServiceList() as $SERVICE_ID => $obService) { ?><option value="<?echo htmlspecialcharsbx($SERVICE_ID)?>"<?if($arRes["SERVICE_ID"] === $SERVICE_ID) echo " selected"?>><?echo htmlspecialcharsex($obService->GetName())?></option><? if($arRes["SERVICE_ID"] === $SERVICE_ID) $bServiceSet = true; } ?> </select> </td> </tr> <?foreach(CCloudStorage::GetServiceList() as $SERVICE_ID => $obService) {?> <tr id="LOCATION_<?echo htmlspecialcharsbx($SERVICE_ID)?>" style="display:<?echo $arRes["SERVICE_ID"] === $SERVICE_ID || !$bServiceSet? "": "none"?>" class="location-tr"> <td><?echo GetMessage("CLO_STORAGE_EDIT_LOCATION")?>:</td> <td> <select name="LOCATION[<?echo htmlspecialcharsbx($SERVICE_ID)?>]"> <? foreach(CCloudStorage::GetServiceLocationList($SERVICE_ID) as $LOCATION_ID => $LOCATION_NAME) { ?><option value="<?echo htmlspecialcharsbx($LOCATION_ID)?>"<?if($arRes["SERVICE_ID"] === $LOCATION_ID) echo " selected"?>><?echo htmlspecialcharsex($LOCATION_NAME)?></option><? } ?> </select> </td> </tr> <?echo $obService->GetSettingsHTML($arRes, $bServiceSet, $arRes["SERVICE_ID"], $bVarsFromForm)?> <?$bServiceSet = true;?> <?}?> <?}?> <?if($ID > 0) {?> <tr class="adm-detail-required-field"> <td><?echo GetMessage("CLO_STORAGE_EDIT_BUCKET")?>:</td> <td><input type="hidden" name="BUCKET" value="<?echo htmlspecialcharsbx($arRes["BUCKET"])?>"><?echo htmlspecialcharsex($arRes["BUCKET"])?></td> </tr> <? } else {?> <tr class="adm-detail-required-field"> <td><?echo GetMessage("CLO_STORAGE_EDIT_BUCKET")?>:</td> <td><input type="text" size="55" name="BUCKET" value="<?echo htmlspecialcharsbx($arRes["BUCKET"])?>"></td> </tr> <?}?> <tr> <td><?echo GetMessage("CLO_STORAGE_EDIT_READ_ONLY")?>:</td> <td><input type="hidden" name="READ_ONLY" value="N"><input type="checkbox" name="READ_ONLY" value="Y"<?if($arRes["READ_ONLY"] === "Y") echo " checked"?>></td> </tr> <tr> <td><?echo GetMessage("CLO_STORAGE_EDIT_CNAME")?>:</td> <td><input type="text" size="55" name="CNAME" value="<?echo htmlspecialcharsbx($arRes["CNAME"])?>"></td> </tr> <? $tabControl->BeginNextTab(); ?> <tr><td align="center"> <? if($bVarsFromForm) $arRules = CCloudStorageBucket::ConvertPOST($_POST); elseif(isset($arRes["FILE_RULES"])) $arRules = unserialize($arRes["FILE_RULES"]); else $arRules = array(); if(!is_array($arRules)) $arRules = array(); ?> <table border="0" cellspacing="0" cellpadding="0" class="internal" align="center" id="tblRULES"> <tr class="heading"> <td><?echo GetMessage("CLO_STORAGE_EDIT_MODULE")?><sup><span class="required">1</span></sup></td> <td><?echo GetMessage("CLO_STORAGE_EDIT_EXTENSIONS")?><sup><span class="required">2</span></sup></td> <td><?echo GetMessage("CLO_STORAGE_EDIT_SIZE")?><sup><span class="required">3</span></sup></td> <td> </td> </tr> <? $ii = 0; foreach($arRules as $rule) { ?> <tr> <td><input name="MODULE[]" type="text" value="<?echo htmlspecialcharsbx($rule["MODULE"])?>" style="width:100%"></td> <td><input name="EXTENSION[]" type="text" value="<?echo htmlspecialcharsbx($rule["EXTENSION"])?>" style="width:100%"></td> <td><input name="SIZE[]" type="text" value="<?echo htmlspecialcharsbx($rule["SIZE"])?>" style="width:100%"></td> <td><img src="/bitrix/themes/.default/images/actions/delete_button.gif" onclick="editDeleteRule(this)" /></td> </tr> <? $ii++; } if($ii == 0 && $ID == 0) { ?> <tr> <td><input name="MODULE[]" type="text" style="width:100%"></td> <td><input name="EXTENSION[]" type="text" style="width:100%"></td> <td><input name="SIZE[]" type="text" style="width:100%"></td> <td><img src="/bitrix/themes/.default/images/actions/delete_button.gif" onclick="editDeleteRule(this)" /></td> </tr> <? $ii=1; } ?> </table> <script type="text/javascript"> BX.ready(function() { BX.addCustomEvent(document.forms.editform, 'onAutoSaveRestore', function(ob, data) { if (data['MODULE[]'] && BX.type.isArray(data['MODULE[]']) && data['MODULE[]'].length > <?=$ii?>) { for (var i=<?=$ii?>; i<data['MODULE[]'].length; i++) editAddRule(); } }); }); </script><br> <a class="adm-btn" href="javascript:void(0)" onclick="editAddRule(this)" hidefocus="true" class="bx-action-href"><?echo GetMessage("CLO_STORAGE_EDIT_ADD_FILE_RULE")?></a> </td></tr> <tr><td> <?echo BeginNote(), '<p>',GetMessage("CLO_STORAGE_EDIT_RULES_NOTE"),'</p>', '<span class="required">1</span> - ',GetMessage("CLO_STORAGE_EDIT_RULES_NOTE1"),'<br />', '<span class="required">2</span> - ',GetMessage("CLO_STORAGE_EDIT_RULES_NOTE2"),'<br />', '<span class="required">3</span> - ',GetMessage("CLO_STORAGE_EDIT_RULES_NOTE3"),'<br />', EndNote(); ?> </td></tr> <? $tabControl->Buttons( array( "back_url"=>"clouds_storage_list.php?lang=".LANGUAGE_ID, ) ); ?> <?echo bitrix_sessid_post();?> <input type="hidden" name="lang" value="<?echo LANGUAGE_ID?>"> <input type="hidden" name="ID" value="<?echo $ID?>"> <? $tabControl->End(); ?> </form> <? $tabControl->ShowWarnings("editform", $message); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php"); ?>admin/operation_description.php000064400000000640150241560060012747 0ustar00<? if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die(); use Bitrix\Main\Localization\Loc; Loc::loadMessages(__FILE__); return array( "CLOUDS_BROWSE" => array( "title" => Loc::getMessage('OP_NAME_CLOUDS_BROWSE'), ), "CLOUDS_UPLOAD" => array( "title" => Loc::getMessage('OP_NAME_CLOUDS_UPLOAD'), ), "CLOUDS_CONFIG" => array( "title" => Loc::getMessage('OP_NAME_CLOUDS_CONFIG'), ), ); admin/clouds_file_search.php000064400000013631150241560060012165 0ustar00<? define("ADMIN_MODULE_NAME", "clouds"); /*.require_module 'standard';.*/ /*.require_module 'pcre';.*/ /*.require_module 'bitrix_main_include_prolog_admin_before';.*/ require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php"); if(!$USER->CanDoOperation("clouds_browse")) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); /*.require_module 'bitrix_clouds_include';.*/ if(!CModule::IncludeModule('clouds')) $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); IncludeModuleLangFile(__FILE__); $bucket_id = 0; $arBuckets = array(); foreach(CCloudStorageBucket::GetAllBuckets() as $arBucket) { if($arBucket["ACTIVE"] == "Y") { $bucket_id = $arBucket["ID"]; $arBuckets[$bucket_id] = $arBucket["BUCKET"]; } } $message = /*.(CAdminMessage).*/null; $sTableID = "tbl_clouds_file_search"; $lAdmin = new CAdminList($sTableID); $lAdmin->InitFilter(array("bucket", "path")); $path = isset($_GET["path"])? $_GET["path"]: $path; $path = preg_replace("#[\\\\\\/]+#", "/", "/".$path."/"); $n = preg_replace("/[^a-zA-Z0-9_:\\[\\]]/", "", $_GET["n"]); if(intval($bucket) <= 0 && count($arBuckets) == 1) $bucket = $bucket_id; //TODO when there is only one cloud storage there is no need for filter or at least we can preset it $arHeaders = array( array( "id" => "FILE_NAME", "content" => GetMessage("CLO_STORAGE_SEARCH_NAME"), "default" => true, ), array( "id" => "FILE_SIZE", "content" => GetMessage("CLO_STORAGE_SEARCH_SIZE"), "align" => "right", "default" => true, ), ); $lAdmin->AddHeaders($arHeaders); $arData = /*.(array[int][string]string).*/array(); $obBucket = new CCloudStorageBucket($bucket); if($obBucket->Init() && $_GET["file"]!=="y") { $arFiles = $obBucket->ListFiles($path); if($path != "/") $arData[] = array("ID" => "D..", "TYPE" => "dir", "NAME" => "..", "SIZE" => ""); if(is_array($arFiles)) { foreach($arFiles["dir"] as $i => $dir) $arData[] = array("ID" => "D".$dir, "TYPE" => "dir", "NAME" => $dir, "SIZE" => ''); foreach($arFiles["file"] as $i => $file) $arData[] = array("ID" => "F".$file, "TYPE" => "file", "NAME" => $file, "SIZE" => $arFiles["file_size"][$i]); } else { $e = $APPLICATION->GetException(); if(is_object($e)) $message = new CAdminMessage(GetMessage("CLO_STORAGE_SEARCH_LIST_ERROR"), $e); } } $rsData = new CDBResult; $rsData->InitFromArray($arData); $rsData = new CAdminResult($rsData, $sTableID); $rsData->NavStart(); $lAdmin->NavText($rsData->GetNavPrint('')); while(is_array($arRes = $rsData->NavNext())) { if($arRes["TYPE"] === "dir") { if($arRes["NAME"] === "..") $link = 'clouds_file_search.php?lang='.LANGUAGE_ID.'&n='.urlencode($n).'&bucket='.$obBucket->ID.'&path='.urlencode(preg_replace('#([^/]+)/$#', '', $path)); else $link = 'clouds_file_search.php?lang='.LANGUAGE_ID.'&n='.urlencode($n).'&bucket='.$obBucket->ID.'&path='.urlencode($path.$arRes["NAME"].'/'); } else { $link = 'clouds_file_search.php?lang='.LANGUAGE_ID.'&n='.urlencode($n).'&file=y&bucket='.$obBucket->ID.'&path='.urlencode($path.$arRes["NAME"]); } $row =& $lAdmin->AddRow($arRes["ID"], $arRes, $link); $showFieldIcon = ""; $showFieldText = ""; if($arRes["TYPE"] === "dir") { $showFieldIcon = '<a href="'.htmlspecialcharsbx($link).'"><span id="fileman_menu_icon_sections" class="adm-submenu-item-link-icon"></span></a>'; $showFieldText = '<a href="'.htmlspecialcharsbx($link).'">'.htmlspecialcharsex($arRes["NAME"]).'</a>'; } else { $showFieldIcon = ""; $showFieldText = '<a href="'.htmlspecialcharsbx($link).'">'.htmlspecialcharsex($arRes["NAME"]).'</a>'; } $showField = '<table cellpadding="0" cellspacing="0" border="0"><tr><td align="left">'.$showFieldIcon.'</td><td align="left"> '.$showFieldText.'</td></tr></table>'; if($arRes["TYPE"] === "dir") { $row->AddViewField("FILE_NAME", $showField); $row->AddViewField("FILE_SIZE", ' '); } else { $row->AddViewField("FILE_NAME", $showField); $row->AddViewField("FILE_SIZE", CFile::FormatSize((float)$arRes["SIZE"])); } } $lAdmin->BeginPrologContent(); if(is_object($message)) echo $message->Show(); if($obBucket->Init() && $_GET["file"] === "y") echo "<script>SelFile('".CUtil::JSEscape(urldecode($obBucket->GetFileSRC(rtrim($path, "/"))))."');</script>"; $lAdmin->EndPrologContent(); $lAdmin->CheckListMode(); $APPLICATION->SetTitle(GetMessage("CLO_STORAGE_SEARCH_TITLE")); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_popup_admin.php"); ?> <form name="form1" method="GET" action="<?echo $APPLICATION->GetCurPage()?>"> <? $arFindFields = Array( "bucket"=>GetMessage("CLO_STORAGE_SEARCH_BUCKET"), "path"=>GetMessage("CLO_STORAGE_SEARCH_PATH"), ); $oFilter = new CAdminFilter($sTableID."_filter", $arFindFields); $oFilter->Begin(); ?> <script language="JavaScript"> function SelFile(name) { if (window.opener && window.opener.BX) { window.opener.BX.onCustomEvent('onCloudFileIsChosen', [name]); } el = window.opener.document.getElementById('<?echo CUtil::JSEscape($n)?>'); if(el) { el.value = name; if (window.opener.BX) window.opener.BX.fireEvent(el, 'change'); } window.close(); } </script> <tr> <td><b><?echo GetMessage("CLO_STORAGE_SEARCH_BUCKET")?></b></td> <td><select name="bucket"> <option value=""><?echo GetMessage("CLO_STORAGE_SEARCH_CHOOSE_BUCKET")?></option> <?foreach($arBuckets as $id => $name):?> <option value="<?echo htmlspecialcharsbx($id)?>" <?if($id == $bucket) echo "selected"?>><?echo htmlspecialcharsex($name)?></option> <?endforeach?> </select></td> </tr> <tr> <td><?echo GetMessage("CLO_STORAGE_SEARCH_PATH")?></td> <td><input type="text" name="path" size="45" value="<?echo htmlspecialcharsbx($path)?>"></td> </tr> <? $oFilter->Buttons(array( "url" => "/bitrix/admin/clouds_file_search.php?lang=".LANGUAGE_ID."&n=".urlencode($n), "table_id" => $sTableID, )); $oFilter->End(); ?> </form> <? $lAdmin->DisplayList(); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_popup_admin.php"); ?>include.php000064400000003065150241560060006703 0ustar00<? /*.require_module 'standard';.*/ /*.require_module 'bitrix_main';.*/ /** * @global CDatabase $DB */ if(!defined("CACHED_b_clouds_file_bucket")) define("CACHED_b_clouds_file_bucket", 360000); if(!defined("CACHED_clouds_file_resize")) define("CACHED_clouds_file_resize", 360000); if(!defined("BX_S3_MIN_UPLOAD_PART_SIZE")) define("BX_S3_MIN_UPLOAD_PART_SIZE", 5242880); //5MB $db_type = strtolower($DB->type); CModule::AddAutoloadClasses( "clouds", array( "CCloudUtil" => "classes/general/util.php", "CCloudStorage" => "classes/general/storage.php", "CAllCloudStorageBucket" => "classes/".$db_type."/storage_bucket.php", "CCloudStorageBucket" => "classes/general/storage_bucket.php", "CCloudStorageService" => "classes/general/storage_service.php", "CCloudStorageService_AmazonS3" => "classes/general/storage_service_s3.php", "CCloudStorageService_GoogleStorage" => "classes/general/storage_service_google.php", "CCloudStorageService_OpenStackStorage" => "classes/general/storage_service_openstack.php", "CCloudStorageService_RackSpaceCloudFiles" => "classes/general/storage_service_rackspace.php", "CCloudStorageService_ClodoRU" => "classes/general/storage_service_clodo.php", "CCloudStorageService_Selectel" => "classes/general/storage_service_selectel.php", "CCloudStorageService_HotBox" => "classes/general/storage_service_hotbox.php", "CCloudStorageUpload" => "classes/general/storage_upload.php", "CCloudSecurityService_AmazonS3" => "classes/general/security_service_s3.php", "CCloudTempFile" => "classes/general/temp_file.php", ) ); ?>options.php000064400000011200150241560060006741 0ustar00<? $module_id = "clouds"; $RIGHT_R = $USER->CanDoOperation('clouds_config'); $RIGHT_W = $USER->CanDoOperation('clouds_config'); if($RIGHT_R || $RIGHT_W) : IncludeModuleLangFile($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/main/options.php"); IncludeModuleLangFile(__FILE__); $arAllOptions = array( array("log_404_errors", GetMessage("CLO_OPTIONS_LOG_404_ERRORS"), array("checkbox")), ); $aTabs = array( array("DIV" => "edit1", "TAB" => GetMessage("MAIN_TAB_SET"), "ICON" => "clouds_settings", "TITLE" => GetMessage("MAIN_TAB_TITLE_SET")), array("DIV" => "edit2", "TAB" => GetMessage("MAIN_TAB_RIGHTS"), "ICON" => "clouds_settings", "TITLE" => GetMessage("MAIN_TAB_TITLE_RIGHTS")), ); $tabControl = new CAdminTabControl("tabControl", $aTabs); CModule::IncludeModule($module_id); if($REQUEST_METHOD=="POST" && strlen($Update.$Apply.$RestoreDefaults) > 0 && $RIGHT_W && check_bitrix_sessid()) { if(strlen($RestoreDefaults)>0) { COption::RemoveOption($module_id); } else { foreach($arAllOptions as $arOption) { $name = $arOption[0]; $val = trim($_REQUEST[$name], " \t\n\r"); if($arOption[2][0]=="checkbox" && $val!="Y") $val="N"; COption::SetOptionString($module_id, $name, $val, $arOption[1]); } } ob_start(); $Update = $Update.$Apply; require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/admin/group_rights2.php"); ob_end_clean(); if(strlen($_REQUEST["back_url_settings"]) > 0) { if((strlen($Apply) > 0) || (strlen($RestoreDefaults) > 0)) LocalRedirect($APPLICATION->GetCurPage()."?mid=".urlencode($module_id)."&lang=".urlencode(LANGUAGE_ID)."&back_url_settings=".urlencode($_REQUEST["back_url_settings"])."&".$tabControl->ActiveTabParam()); else LocalRedirect($_REQUEST["back_url_settings"]); } else { LocalRedirect($APPLICATION->GetCurPage()."?mid=".urlencode($module_id)."&lang=".urlencode(LANGUAGE_ID)."&".$tabControl->ActiveTabParam()); } } ?> <form method="post" action="<?echo $APPLICATION->GetCurPage()?>?mid=<?=urlencode($module_id)?>&lang=<?=LANGUAGE_ID?>"> <? $tabControl->Begin(); $tabControl->BeginNextTab(); foreach($arAllOptions as $arOption): $val = COption::GetOptionString($module_id, $arOption[0]); $type = $arOption[2]; ?> <tr> <td width="40%" nowrap <?if($type[0]=="textarea") echo 'class="adm-detail-valign-top"'?>> <label for="<?echo htmlspecialcharsbx($arOption[0])?>"><?echo $arOption[1]?></label> <td width="60%"> <?if($type[0]=="checkbox"):?> <input type="checkbox" name="<?echo htmlspecialcharsbx($arOption[0])?>" id="<?echo htmlspecialcharsbx($arOption[0])?>" value="Y"<?if($val=="Y")echo" checked";?>> <?elseif($type[0]=="text"):?> <input type="text" size="<?echo $type[1]?>" maxlength="255" value="<?echo htmlspecialcharsbx($val)?>" name="<?echo htmlspecialcharsbx($arOption[0])?>" id="<?echo htmlspecialcharsbx($arOption[0])?>"> <?elseif($type[0]=="textarea"):?> <textarea rows="<?echo $type[1]?>" cols="<?echo $type[2]?>" name="<?echo htmlspecialcharsbx($arOption[0])?>" id="<?echo htmlspecialcharsbx($arOption[0])?>"><?echo htmlspecialcharsbx($val)?></textarea> <?elseif($type[0]=="selectbox"): ?><select name="<?echo htmlspecialcharsbx($arOption[0])?>"><? foreach ($type[1] as $key => $value) { ?><option value="<?echo $key?>"<?if($val==$key)echo" selected"?>><?echo htmlspecialcharsbx($value)?></option><? } ?></select><? endif?> </td> </tr> <?endforeach?> <?$tabControl->BeginNextTab();?> <?require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/admin/group_rights2.php");?> <?$tabControl->Buttons();?> <input <?if(!$RIGHT_W) echo "disabled" ?> type="submit" name="Update" value="<?=GetMessage("MAIN_SAVE")?>" title="<?=GetMessage("MAIN_OPT_SAVE_TITLE")?>" class="adm-btn-save"> <input <?if(!$RIGHT_W) echo "disabled" ?> type="submit" name="Apply" value="<?=GetMessage("MAIN_OPT_APPLY")?>" title="<?=GetMessage("MAIN_OPT_APPLY_TITLE")?>"> <?if(strlen($_REQUEST["back_url_settings"])>0):?> <input <?if(!$RIGHT_W) echo "disabled" ?> type="button" name="Cancel" value="<?=GetMessage("MAIN_OPT_CANCEL")?>" title="<?=GetMessage("MAIN_OPT_CANCEL_TITLE")?>" onclick="window.location='<?echo htmlspecialcharsbx(CUtil::addslashes($_REQUEST["back_url_settings"]))?>'"> <input type="hidden" name="back_url_settings" value="<?=htmlspecialcharsbx($_REQUEST["back_url_settings"])?>"> <?endif?> <input <?if(!$RIGHT_W) echo "disabled" ?> type="submit" name="RestoreDefaults" title="<?echo GetMessage("MAIN_HINT_RESTORE_DEFAULTS")?>" onclick="return confirm('<?echo AddSlashes(GetMessage("MAIN_HINT_RESTORE_DEFAULTS_WARNING"))?>')" value="<?echo GetMessage("MAIN_RESTORE_DEFAULTS")?>"> <?=bitrix_sessid_post();?> <?$tabControl->End();?> </form> <?endif;?>
/home/user/web/pansionat-v-yaroslavle.ru/public_html/70645/../331ab/./clouds.tar