AliOssForTypecho/Plugin.php

771 lines
36 KiB
PHP
Raw Normal View History

2015-09-30 03:26:19 +08:00
<?php
require_once 'aliyun-oss-php-sdk-2.4.3/autoload.php';
use OSS\OssClient;
use OSS\Core\OssException;
2015-09-30 03:26:19 +08:00
/**
* AliyunOSS储存Typecho上传附件.
*
* @package AliOssForTypecho
2015-09-30 03:26:19 +08:00
* @author droomo.
2020-06-27 16:10:21 +08:00
* @version 1.1.8
* @link https://www.droomo.top/
2015-09-30 03:26:19 +08:00
*/
2020-06-27 13:49:48 +08:00
class AliOssForTypecho_Plugin extends Typecho_Widget implements Typecho_Plugin_Interface {
2020-06-25 20:42:53 +08:00
const UPLOAD_DIR = 'usr/uploads/';//上传文件目录,相对网站根目录
const LOG_SUFFIX = '__oss-plugin-log/';//日志目录放置于UPLOAD_DIR下
2015-09-30 03:26:19 +08:00
2020-06-27 13:49:48 +08:00
public function api_version() {
echo __FUNCTION__;
var_dump (self::get_plugin_information()['version']);
}
public function api_log() {
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
} else {
}
}
public static function get_plugin_information() {
Typecho_Widget::widget('Widget_Plugins_List@activated', 'activated=1')->to($activatedPlugins);
$activatedPlugins = json_decode(json_encode($activatedPlugins),true);
$plugins_list = $activatedPlugins['stack'];
$plugins_info = array();
for ($i = 0; $i < count($plugins_list); $i++){
if($plugins_list[$i]['title'] == 'AliOssForTypecho'){
$plugins_info = $plugins_list[$i];
break;
}
}
if (count($plugins_info) < 1) {
return false;
}
return $plugins_info;
}
2015-09-30 03:26:19 +08:00
/**
* 激活插件方法,如果激活失败,直接抛出异常
*
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
2020-06-27 13:49:48 +08:00
public static function activate() {
2015-09-30 03:26:19 +08:00
Typecho_Plugin::factory('Widget_Upload')->uploadHandle = array('AliOssForTypecho_Plugin', 'uploadHandle');
Typecho_Plugin::factory('Widget_Upload')->modifyHandle = array('AliOssForTypecho_Plugin', 'modifyHandle');
Typecho_Plugin::factory('Widget_Upload')->deleteHandle = array('AliOssForTypecho_Plugin', 'deleteHandle');
Typecho_Plugin::factory('Widget_Upload')->attachmentHandle = array('AliOssForTypecho_Plugin', 'attachmentHandle');
Typecho_Plugin::factory('Widget_Upload')->attachmentDataHandle = array('AliOssForTypecho_Plugin', 'attachmentDataHandle');
2020-06-27 13:49:48 +08:00
Helper::addRoute('__alioss_for_tp_plugin_version__', '/__alioss_for_tp_plugin_api__/version', 'AliOssForTypecho_Plugin', 'api_version');
Helper::addRoute('__alioss_for_tp_plugin_log__', '/__alioss_for_tp_plugin_api__/log', 'AliOssForTypecho_Plugin', 'api_log');
2015-09-30 03:26:19 +08:00
return _t('启用成功,请进行相应设置!');
}
/**
* 禁用插件方法,如果禁用失败,直接抛出异常
*
* @static
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
2020-06-27 13:49:48 +08:00
public static function deactivate() {
Helper::removeRoute('__alioss_for_tp_plugin_version__');
Helper::removeRoute('__alioss_for_tp_plugin_log__');
}
2015-09-30 03:26:19 +08:00
/**
* 获取插件配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form 配置面板
* @return void
*/
2020-06-27 13:49:48 +08:00
public static function config(Typecho_Widget_Helper_Form $form) {
2020-06-25 21:10:02 +08:00
$upload_root = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__);
2020-06-26 19:43:40 +08:00
$log_file_name = $upload_root . self::LOG_SUFFIX . 'error.log';
if (is_writable($upload_root)) {
2020-06-27 15:31:26 +08:00
$log_content = '恭喜!暂无错误日志产生,请继续保持维护~';
$log_color = '#009900';
2020-06-26 19:43:40 +08:00
if (!file_exists($log_file_name)) {
self::makeUploadDir($upload_root . self::LOG_SUFFIX);
fopen($log_file_name, 'w');
2020-06-27 15:31:26 +08:00
if (!file_exists($log_file_name)) {
2020-06-27 16:10:21 +08:00
$log_content = '无法创建日志文件请检查权限设置开启SELinux的用户注意合理配置权限';
2020-06-27 15:31:26 +08:00
$log_color = '#f00000';
}
} else {
try {
$content = file_get_contents($log_file_name);
if ($content) {
$log_content = $content;
$log_color = '#dd0000';
}
} catch (Exception $e) {
$log_content = '注意!无法读取日志文件,请检查文件状态!';
$log_color = '#f00000';
2020-06-25 21:10:02 +08:00
}
}
} else {
$log_content = '!!!注意!!!
当前网站上传目录无写入权限,无法记录日志!
2020-06-27 16:10:21 +08:00
请给路径 '.$upload_root.' 赋予写入权限。开启SELinux的用户注意合理配置权限。';
2020-06-25 21:10:02 +08:00
$log_color = '#f00000';
}
2020-06-26 19:43:40 +08:00
?>
<div>
<h3>插件使用说明</h3>
<ol>
2020-06-25 20:42:53 +08:00
<li>插件基于<a href="https://github.com/aliyun/aliyun-oss-php-sdk/releases/tag/v2.3.1">aliyun-oss-php-sdk Release 2.3.1</a>开发,
若以后SDK开发包更新导致插件不可用请到 <a target="_blank" href="https://www.droomo.top/AliOssForTypecho.html">我的博客^-^</a>获取新版本插件如果我还用typecho、阿里云OSS就会更新。<br/></li>
2020-06-27 16:10:21 +08:00
<li>为保证正确记录日志,请赋予以下目录写权限:<code style="color:#333;font-size:12px;"><?php echo $upload_root;?></code>并定期查阅日志处理事件错误。开启SELinux的用户注意合理配置权限。</li>
2020-06-27 14:07:40 +08:00
<li>当文件成功上传到OSS但保存到服务器失败时总体进度会显示失败。在OSS中的文件不会自动删除请根据错误日志自行处理。</li>
<li>运行在云应用引擎上的站点“在服务器保留备份”选项无效,且无法记录日志。</li>
<li>旧版本Typecho存在无法上传大写扩展名文件的bug请更新Typecho程序。<br/></li>
2020-06-25 20:42:53 +08:00
<li>如有问题或建议请到 <a target="_blank" href="https://www.droomo.top/AliOssForTypecho.html">我的博客https://www.droomo.top/AliOssForTypecho.html</a> 留言</li>
2020-06-25 21:10:02 +08:00
</ol>
<p>以下是本插件产生的错误日志,请定期查看并处理:</p>
2020-06-27 14:22:39 +08:00
<p>日志文件是&nbsp;&nbsp;<span style="color:#666;font-sieze:8px"><?php echo $log_file_name;?><span></p>
2020-06-26 19:43:40 +08:00
<div style="width:98%;margin: 0 auto">
<textarea style="color:<?php echo $log_color;?>;height:160px;width:100%;"><?php echo $log_content;?></textarea></div>
</div>
<?php
$buketName = new Typecho_Widget_Helper_Form_Element_Text('bucketName', NULL, null,
2015-09-30 03:26:19 +08:00
_t('Bucket名称'), _t('请填写Buket名称'));
$form->addInput($buketName->addRule('required', _t('必须填写Bucket名称')));
$accessKeyId = new Typecho_Widget_Helper_Form_Element_Text('accessKeyId', NULL, null,
_t('ACCESS KEY ID'), _t('请填写ACCESS KEY ID'));
$form->addInput($accessKeyId->addRule('required', _t('必须填写ACCESS KEY ID')));
2015-09-30 03:26:19 +08:00
$accessKeySecret = new Typecho_Widget_Helper_Form_Element_Text('accessKeySecret', NULL, null,
_t('ACCESS KEY SECRET'), _t('请填写请填写ACCESS KEY SECRET'));
$form->addInput($accessKeySecret->addRule('required', _t('必须填写ACCESS_KEY')));
2015-09-30 03:26:19 +08:00
$endPoint = new Typecho_Widget_Helper_Form_Element_Select('endPoint',
array(
2020-06-25 16:55:45 +08:00
"oss-cn-hangzhou" => "华东1杭州oss-cn-hangzhou",
"oss-cn-shanghai" => "华东2上海oss-cn-shanghai",
"oss-cn-qingdao" => "华北1青岛oss-cn-qingdao",
"oss-cn-beijing" => "华北2北京oss-cn-beijing",
"oss-cn-zhangjiakou" => "华北3张家口oss-cn-zhangjiakou",
"oss-cn-huhehaote" => "华北5呼和浩特oss-cn-huhehaote",
"oss-cn-wulanchabu" => "华北6乌兰察布oss-cn-wulanchabu",
"oss-cn-shenzhen" => "华南1深圳oss-cn-shenzhen",
"oss-cn-heyuan" => "华南2河源oss-cn-heyuan",
"oss-cn-chengdu" => "西南1成都oss-cn-chengdu",
"oss-cn-hongkong" => "中国香港oss-cn-hongkong",
"oss-us-west-1" => "美国西部1硅谷oss-us-west-1",
"oss-us-east-1" => "美国东部1弗吉尼亚oss-us-east-1",
"oss-ap-southeast-1" =>"亚太东南1新加坡oss-ap-southeast-1",
"oss-ap-southeast-2" =>"亚太东南2悉尼oss-ap-southeast-2",
"oss-ap-southeast-3" =>"亚太东南3吉隆坡oss-ap-southeast-3",
"oss-ap-southeast-5" =>"亚太东南5雅加达oss-ap-southeast-5",
"oss-ap-northeast-1" =>"亚太东北1日本oss-ap-northeast-1",
"oss-ap-south-1" => "亚太南部1孟买oss-ap-south-1",
"oss-eu-central-1" => "欧洲中部1法兰克福oss-eu-central-1",
"oss-eu-west-1" => "英国伦敦oss-eu-west-1",
"oss-me-east-1" => "中东东部1迪拜oss-me-east-1",
2020-06-25 20:42:53 +08:00
"other" => '自定义'
),
'oss-cn-qingdao',
2020-06-25 16:55:45 +08:00
_t('区域选择(若区域不在列表中则选择自定义,然后填写区域)'), '');
2015-09-30 03:26:19 +08:00
$form->addInput($endPoint);
$endPointType = new Typecho_Widget_Helper_Form_Element_Select('endPointType',
array(
2020-06-26 19:43:40 +08:00
".aliyuncs.com" => '外网',
"-internal.aliyuncs.com" => '内网',
),
'.aliyuncs.com', '<label class="AliossForTypecho-mark-other-endpoint-hide">选择服务器与OSS连接方式</label>',
'<span class="AliossForTypecho-mark-other-endpoint-hide">在你了解两种连接方式的不同作用的情况下修改此选项</span>');
$form->addInput($endPointType);
2015-09-30 03:26:19 +08:00
2020-06-25 20:42:53 +08:00
$otherEndPoint = new Typecho_Widget_Helper_Form_Element_Text('otherEndPoint', NULL, '',
'<label class="AliossForTypecho-mark-other-endpoint-show">自定义EndPoint</label>', '<span class="AliossForTypecho-mark-other-endpoint-show">
填写全部Endpoint地址通常以\'.aliyuncs.com\'或\'-internal.aliyuncs.com\'结尾。开头不包含http://,结尾不包含"/"。<br/>例如"oss-cn-qingdao.aliyuncs.com"</span>');
2015-09-30 03:26:19 +08:00
$form->addInput($otherEndPoint);
$userDir = new Typecho_Widget_Helper_Form_Element_Text('userDir', NULL, 'typecho/',
_t('要储存的路径'), _t('请填写文件储存的路径相对OSS根目录以字母或数字开头以"/"结尾。留空则上传到根目录。'));
$form->addInput($userDir);
$cdnUrl = new Typecho_Widget_Helper_Form_Element_Text('cdnUrl', NULL, '',
_t('自定义CDN域名'), '请填写自定义域名留空则使用外网Endpoint访问以http://或https://开头,以"/"结尾');
2015-09-30 03:26:19 +08:00
$form->addInput($cdnUrl);
$diy_style = new Typecho_Widget_Helper_Form_Element_Text('des', NULL, '', _t('默认自定义样式'),
_t('通过后缀的方式使用自定义样式,留空为不使用。使用详情见<a target="_blank" href="https://help.aliyun.com/document_detail/48884.html">阿里云文档</a>'));
$form->addInput($diy_style);
2020-06-26 19:43:40 +08:00
$form->addInput(new Typecho_Widget_Helper_Form_Element_Radio('ifLoaclSave', array( "1" => '保留', "0" => '不保留' ), "1",
_t('在服务器保留备份'), _t('是否在服务器保留备份')));
?>
<script>
2020-06-26 20:21:11 +08:00
window.onload = function() {
2020-06-27 13:49:48 +08:00
(function() {
2020-06-26 20:21:11 +08:00
var AliossForTypecho_otherSelected = document.getElementsByName("endPoint")[0].value === "other";
var AliossForTypecho_otherEndpointShowingTags = document.getElementsByClassName("AliossForTypecho-mark-other-endpoint-show");
var AliossForTypecho_otherEndpointHiddingTags = document.getElementsByClassName("AliossForTypecho-mark-other-endpoint-hide");
var AliossForTypecho_otherEndPointInputTag = document.getElementsByName("otherEndPoint")[0];
var AliossForTypecho_endPointTypeInputTag = document.getElementsByName("endPointType")[0];
var AliossForTypecho_loadLabels = function () {
var AliossForTypecho_s1 = null, AliossForTypecho_s2 = null;
if (AliossForTypecho_otherSelected) {
AliossForTypecho_s1 = "none";
AliossForTypecho_s2 = "block";
AliossForTypecho_otherEndPointInputTag.type = "text";
} else {
AliossForTypecho_s2 = "none";
AliossForTypecho_s1 = "block";
AliossForTypecho_otherEndPointInputTag.type = "hidden";
AliossForTypecho_endPointTypeInputTag.type = "";
}
AliossForTypecho_endPointTypeInputTag.style.display = AliossForTypecho_s1;
for (var AliossForTypecho_i = 0; AliossForTypecho_i < AliossForTypecho_otherEndpointShowingTags.length; AliossForTypecho_i++) {
AliossForTypecho_otherEndpointShowingTags[AliossForTypecho_i].style.display = AliossForTypecho_s2;
}
for (var AliossForTypecho_i = 0; AliossForTypecho_i < AliossForTypecho_otherEndpointHiddingTags.length; AliossForTypecho_i++) {
AliossForTypecho_otherEndpointHiddingTags[AliossForTypecho_i].style.display = AliossForTypecho_s1;
}
};
document.getElementsByName("endPoint")[0].onchange = function(e) {
AliossForTypecho_otherSelected = e.target.value === "other";
2020-06-26 19:43:40 +08:00
AliossForTypecho_loadLabels();
2020-06-26 20:21:11 +08:00
};
AliossForTypecho_loadLabels();
})();
}
2020-06-26 19:43:40 +08:00
</script>
<?php
2015-09-30 03:26:19 +08:00
}
/**
* 个人用户的配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form
* @return void
*/
2020-06-27 13:49:48 +08:00
public static function personalConfig(Typecho_Widget_Helper_Form $form) {}
2015-09-30 03:26:19 +08:00
/**
* 上传文件处理函数
*
* @access public
* @param array $file 上传的文件
* @return mixed
*/
2020-06-27 13:49:48 +08:00
public static function uploadHandle($file) {
if (empty($file['name'])) {
2015-09-30 03:26:19 +08:00
return FALSE;
}
2020-06-25 20:42:53 +08:00
$ext = self::getExtentionName($file['name']);
if (!self::checkFileType($ext)) {
return FALSE;
}
if (isset($file['tmp_name'])) {
$content = file_get_contents($file['tmp_name']);
} else if (isset($file['bytes'])) {
$content = $file['bytes'];
} else {
return FALSE;
}
2020-06-26 19:43:40 +08:00
$upload_root = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__);
$options = Typecho_Widget::widget('Widget_Options');
2020-06-25 20:42:53 +08:00
$user_dir = $options->plugin('AliOssForTypecho')->userDir;
$bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
$end_point = 'http://' . (($options->plugin('AliOssForTypecho')->endPoint === "other") ?
$options->plugin('AliOssForTypecho')->otherEndPoint :
$options->plugin('AliOssForTypecho')->endPoint . $options->plugin('AliOssForTypecho')->endPointType);
$access_id = $options->plugin('AliOssForTypecho')->accessKeyId;
$access_key = $options->plugin('AliOssForTypecho')->accessKeySecret;
2015-09-30 03:26:19 +08:00
2020-06-25 20:42:53 +08:00
try {
$oss_client = new OssClient($access_id, $access_key, $end_point);
2020-06-26 19:43:40 +08:00
$oss_client->doesBucketExist($bucket_name);
2020-06-25 20:42:53 +08:00
} catch (Exception $e) {
2020-06-26 21:29:45 +08:00
$error = '错误连接OSS Client实例失败' . "\r\n" .
2020-06-26 19:43:40 +08:00
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
2015-09-30 03:26:19 +08:00
}
2020-06-25 20:42:53 +08:00
$save_on_server = $options->plugin('AliOssForTypecho')->ifLoaclSave;
$file_origin_name = self::getSafeName($file['name']);
2020-06-25 20:42:53 +08:00
$relative_path = date('Y/m/d/');
$remote_file_name = $user_dir . $relative_path . $file_origin_name;
if ($save_on_server === "1" && !Typecho_Common::isAppEngine()) {
$upload_root = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__);
$local_file_name = $upload_root . $relative_path . $file_origin_name;
try{
$exist_on_oss = $oss_client->doesObjectExist($bucket_name, $remote_file_name);
$exist_on_server = file_exists($local_file_name);
} catch(OssException $e) {
2020-06-26 19:43:40 +08:00
$error = '错误检查OSS或本地服务器中中是否存在同名文件时失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
2020-06-25 20:42:53 +08:00
return false;
}
if ($exist_on_oss || $exist_on_server) {
// find a name neither exist on oss nor the server
$pathinfo = pathinfo($file_origin_name);
for ($i = 1;; $i++) {
$file_origin_name = $pathinfo['filename'] . '(' . strval($i) . ').' . self::getExtentionName($file_origin_name);
$remote_file_name = $user_dir . $relative_path . $file_origin_name;
$local_file_name = $upload_root . $relative_path . $file_origin_name;
try{
$exist_on_oss = $oss_client->doesObjectExist($bucket_name, $remote_file_name);
$exist_on_server = file_exists($local_file_name);
} catch(OssException $e) {
2020-06-26 19:43:40 +08:00
$error = '错误检查OSS或本地服务器中中是否存在同名文件时失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
2020-06-25 20:42:53 +08:00
return false;
}
2020-06-25 20:42:53 +08:00
if ($exist_on_oss || $exist_on_server) {
} else {
break;
}
}
}
} else {
2020-06-25 20:42:53 +08:00
try{
$exist_on_oss = $oss_client->doesObjectExist($bucket_name, $remote_file_name);
} catch(OssException $e) {
2020-06-26 19:43:40 +08:00
$error = '错误检查OSS中是否存在同名文件时失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
2020-06-25 20:42:53 +08:00
return false;
}
if ($exist_on_oss || $exist_on_server) {
// find a name not exist on oss
$pathinfo = pathinfo($file_origin_name);
for ($i = 1;; $i++) {
$file_origin_name = $pathinfo['filename'] . '(' . strval($i) . ').' . self::getExtentionName($file_origin_name);
$remote_file_name = $user_dir . $relative_path . $file_origin_name;
try{
$exist_on_oss = $oss_client->doesObjectExist($bucket_name, $remote_file_name);
} catch(OssException $e) {
2020-06-26 19:43:40 +08:00
$error = '错误检查OSS中是否存在同名文件时失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
2020-06-25 20:42:53 +08:00
return false;
}
if (!$exist_on_oss) {
break;
}
}
}
}
2015-09-30 03:26:19 +08:00
2020-06-25 20:42:53 +08:00
try{
$ali_response = $oss_client->putObject($bucket_name, $remote_file_name, $content);
} catch(OssException $e) {
2020-06-26 19:43:40 +08:00
$error = '错误将文件储存到OSS失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
2020-06-25 20:42:53 +08:00
return false;
}
if (200 != $ali_response['info']['http_code']) {
2020-06-26 21:29:45 +08:00
$error = '错误将文件储存到OSS时返回码不正常' . "\r\n" .
2020-06-26 19:43:40 +08:00
'错误码:' . $ali_response['info']['http_code'] . "\r\n" .
'远程文件:' . $remote_file_name . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
} else {
2020-06-25 20:42:53 +08:00
if ($save_on_server === "1" && !Typecho_Common::isAppEngine()) {
$file_dir_name = dirname($local_file_name);
2020-06-26 21:29:45 +08:00
$dir_exist = true;
2020-06-25 20:42:53 +08:00
2020-06-26 21:29:45 +08:00
if (!is_dir($file_dir_name) && !self::makeUploadDir($file_dir_name)) {
$dir_exist = false;
2015-09-30 03:26:19 +08:00
}
2020-06-26 21:29:45 +08:00
2020-06-25 20:42:53 +08:00
if ($dir_exist) {
if (!file_put_contents($local_file_name, $content)) {
2020-06-27 16:10:21 +08:00
$error = '错误文件已保存到OSS将文件储存到本地服务器时失败请手动删除OSS上的文件开启SELinux的用户注意合理配置权限。' . "\r\n" .
2020-06-26 19:43:40 +08:00
'文件路径:' . $local_file_name . "\r\n" .
'远程文件:' . $remote_file_name . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
2020-06-25 20:42:53 +08:00
return false;
2015-09-30 03:26:19 +08:00
}
} else {
2020-06-27 16:10:21 +08:00
$error = '错误文件已保存到OSS将文件储存到本地服务器时创建目录失败请检查服务器权限设置开启SELinux的用户注意合理配置权限。' . "\r\n" .
2020-06-26 19:43:40 +08:00
'无法创建路径:' . $file_dir_name . "\r\n" .
'远程文件:' . $remote_file_name . "\r\n" .
2015-09-30 03:26:19 +08:00
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
2020-06-26 19:43:40 +08:00
self::my_error_log($error);
return false;
2015-09-30 03:26:19 +08:00
}
}
return array(
'name' => $file_origin_name,
2020-06-26 19:43:40 +08:00
'path' => $relative_path . $file_origin_name,
'size' => intval($ali_response['oss-requestheaders']['Content-Length']),
'type' => $ext,
'mime' => $ali_response['oss-requestheaders']['Content-Type']
);
2020-06-25 20:42:53 +08:00
2015-09-30 03:26:19 +08:00
}
}
/**
* 修改文件处理函数
*
* @access public
* @param array $content 老文件
* @param array $file 新上传的文件
* @return mixed
*/
public static function modifyHandle($content, $file)
{
if (empty($file['name'])) {
return false;
}
2020-06-26 21:29:45 +08:00
$ext = self::getExtentionName($file['name']);
2020-06-26 19:43:40 +08:00
if ($content['attachment']->type != $ext) {
return false;
}
if (isset($file['tmp_name'])) {
2020-06-26 21:29:45 +08:00
$new_file_content = file_get_contents($file['tmp_name']);
2020-06-26 19:43:40 +08:00
} else if (isset($file['bytes'])) {
2020-06-26 21:29:45 +08:00
$new_file_content = $file['bytes'];
2020-06-26 19:43:40 +08:00
} else {
return false;
}
2015-09-30 03:26:19 +08:00
$options = Typecho_Widget::widget('Widget_Options');
$userDir = $options->plugin('AliOssForTypecho')->userDir;
$bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
$end_point = 'http://' . (($options->plugin('AliOssForTypecho')->endPoint === "other") ?
$options->plugin('AliOssForTypecho')->otherEndPoint :
$options->plugin('AliOssForTypecho')->endPoint . $options->plugin('AliOssForTypecho')->endPointType);
$access_id = $options->plugin('AliOssForTypecho')->accessKeyId;
$access_key = $options->plugin('AliOssForTypecho')->accessKeySecret;
$path = $content['attachment']->path;
2020-06-26 21:46:10 +08:00
2020-06-26 21:29:45 +08:00
$remote_file_name = $userDir . $path;
2020-06-26 21:46:10 +08:00
$ifLoaclSave = $options->plugin('AliOssForTypecho')->ifLoaclSave;
$upload_root = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__);
$local_file_name = $upload_root . $path;
if ($ifLoaclSave && (!is_writable($upload_root) || !is_writable($local_file_name))) {
2020-06-27 16:10:21 +08:00
$error = '错误修改文件失败旧文件无写权限开启SELinux的用户注意合理配置权限。' . "\r\n" .
2020-06-26 21:46:10 +08:00
'本地文件:' . $local_file_name . "\r\n" .
'远程文件:' . $remote_file_name . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
}
2015-09-30 03:26:19 +08:00
try {
2020-06-25 20:42:53 +08:00
$oss_client = new OssClient($access_id, $access_key, $end_point);
2020-06-26 19:43:40 +08:00
$oss_client->doesBucketExist($bucket_name);
} catch (Exception $e) {
2020-06-26 21:29:45 +08:00
$error = '错误连接OSS Client实例失败' . "\r\n" .
2020-06-26 19:43:40 +08:00
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
}
2015-09-30 03:26:19 +08:00
2020-06-26 21:29:45 +08:00
try{
$ali_response = $oss_client->putObject($bucket_name, $remote_file_name, $new_file_content);
} catch(OssException $e) {
$error = '错误将文件储存到OSS时失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
}
if (200 != $ali_response['info']['http_code']) {
2020-06-26 21:29:45 +08:00
$error = '错误将文件储存到OSS时返回码不正常' . "\r\n" .
'错误码:' . $ali_response['info']['http_code'] . "\r\n" .
'远程文件:' . $remote_file_name . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
2020-06-26 19:43:40 +08:00
return false;
2020-06-26 21:46:10 +08:00
} else {
2020-06-25 20:42:53 +08:00
if ($ifLoaclSave === "1" && !Typecho_Common::isAppEngine()) {
2020-06-26 21:29:45 +08:00
if (file_exists($local_file_name) && !unlink($local_file_name)) {
$error = '错误:修改文件失败,无法删除旧文件' . "\r\n" .
'本地文件:' . $local_file_name . "\r\n" .
2020-06-26 21:46:10 +08:00
'远程文件:' . $remote_file_name . "\r\n" .
2020-06-26 21:29:45 +08:00
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
}
2020-06-25 20:42:53 +08:00
2020-06-26 21:29:45 +08:00
$file_dir_name = dirname($local_file_name);
$dir_exist = true;
2015-09-30 03:26:19 +08:00
2020-06-26 21:29:45 +08:00
if (!is_dir($file_dir_name) && !self::makeUploadDir($file_dir_name)) {
$dir_exist = false;
2015-09-30 03:26:19 +08:00
}
2020-06-26 21:29:45 +08:00
if ($dir_exist) {
if (!file_put_contents($local_file_name, $new_file_content)) {
$error = '错误文件已保存到OSS将文件储存到本地服务器时失败请手动删除OSS上的文件' . "\r\n" .
'文件路径:' . $local_file_name . "\r\n" .
'远程文件:' . $remote_file_name . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
2015-09-30 03:26:19 +08:00
}
2020-06-25 20:42:53 +08:00
} else {
2020-06-26 21:29:45 +08:00
$error = '错误文件已保存到OSS将文件储存到本地服务器时创建目录失败请检查服务器权限设置请手动删除OSS上的文件' . "\r\n" .
'无法创建路径:' . $file_dir_name . "\r\n" .
2020-06-26 19:43:40 +08:00
'远程文件:' . $remote_file_name . "\r\n" .
2015-09-30 03:26:19 +08:00
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
2020-06-26 19:43:40 +08:00
self::my_error_log($error);
return false;
2015-09-30 03:26:19 +08:00
}
}
}
2015-09-30 03:26:19 +08:00
return array(
'name' => $content['attachment']->name,
'path' => $path,
'size' => intval($ali_response['oss-requestheaders']['Content-Length']),
'type' => $ext,
'mime' => $ali_response['oss-requestheaders']['Content-Type']
2015-09-30 03:26:19 +08:00
);
}
/**
* 删除文件
*
* @access public
* @param array $content 文件相关信息
* @return string
*/
public static function deleteHandle(array $content)
{
$options = Typecho_Widget::widget('Widget_Options');
$userDir = $options->plugin('AliOssForTypecho')->userDir;
$bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
$end_point = 'http://' . (($options->plugin('AliOssForTypecho')->endPoint === "other") ?
2020-06-26 19:43:40 +08:00
$options->plugin('AliOssForTypecho')->otherEndPoint :
$options->plugin('AliOssForTypecho')->endPoint . $options->plugin('AliOssForTypecho')->endPointType);
$access_id = $options->plugin('AliOssForTypecho')->accessKeyId;
$access_key = $options->plugin('AliOssForTypecho')->accessKeySecret;
2020-06-26 19:43:40 +08:00
$ifLoaclSave = $options->plugin('AliOssForTypecho')->ifLoaclSave;
2020-06-26 20:21:11 +08:00
$path = $content['attachment']->path;
$object_name = $userDir . $path;
try {
2020-06-25 20:42:53 +08:00
$oss_client = new OssClient($access_id, $access_key, $end_point);
2020-06-26 19:43:40 +08:00
$oss_client->doesBucketExist($bucket_name);
} catch (Exception $e) {
2020-06-26 21:29:45 +08:00
$error = '错误删除文件失败无法连接OSS Client实例' . "\r\n" .
2020-06-26 19:43:40 +08:00
'错误描述:' . $e->getMessage() . "\r\n" .
2020-06-26 20:21:11 +08:00
'OSS文件:' . $object_name . "\r\n" .
2020-06-26 19:43:40 +08:00
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
return false;
}
2015-09-30 03:26:19 +08:00
2020-06-26 19:43:40 +08:00
try {
$ali_response = $oss_client->deleteObject($bucket_name, $object_name);
} catch (Exception $e) {
$error = '错误删除OSS文件失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
2020-06-26 20:21:11 +08:00
'OSS文件 ' . $object_name . "\r\n" .
2020-06-26 19:43:40 +08:00
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
}
2020-06-26 21:29:45 +08:00
2020-06-26 20:21:11 +08:00
$delete_local_succeed = true;
if ($ifLoaclSave === "1" && !Typecho_Common::isAppEngine()) {
2020-06-25 20:42:53 +08:00
$upload_root = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__);
2020-06-26 19:43:40 +08:00
$local_file_name = $upload_root . $path;
2020-06-26 20:21:11 +08:00
$delete_local_succeed = false;
if (file_exists($local_file_name)) {
2020-06-26 21:59:45 +08:00
if (!is_writable($local_file_name)) {
2020-06-26 20:21:11 +08:00
$error = '错误:删除本地文件失败,请检查权限设置' . "\r\n" .
2020-06-26 21:59:45 +08:00
'文件路径:' . $local_file_name . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
2020-06-26 20:21:11 +08:00
self::my_error_log($error);
2020-06-26 21:59:45 +08:00
} else {
try {
$delete_local_succeed = unlink($local_file_name);
} catch (Exception $e) {
$error = '错误:删除本地文件失败' . "\r\n" .
'错误描述:' . $e->getMessage() . "\r\n" .
'文件路径:' . $local_file_name . "\r\n" .
'时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
self::my_error_log($error);
}
2020-06-26 20:21:11 +08:00
}
} else {
$delete_local_succeed = true;
2015-09-30 03:26:19 +08:00
}
}
2020-06-26 19:43:40 +08:00
return $delete_local_succeed && ($ali_response['info']['http_code'] === 204);
2015-09-30 03:26:19 +08:00
}
/**
* 获取实际文件绝对访问路径
*
* @access public
* @param array $content 文件相关信息
* @return string
*/
public static function attachmentHandle(array $content) {
$options = Typecho_Widget::widget('Widget_Options');
2015-09-30 03:26:19 +08:00
$cdnUrl = $options->plugin('AliOssForTypecho')->cdnUrl;
$userDir = $options->plugin('AliOssForTypecho')->userDir;
$diy_style = $options->plugin('AliOssForTypecho')->des;
2020-06-26 19:43:40 +08:00
if (empty($cdnUrl)) {
2015-09-30 03:26:19 +08:00
$bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
$end_point = ($options->plugin('AliOssForTypecho')->endPoint === "other") ?
$options->plugin('AliOssForTypecho')->otherEndPoint :
$options->plugin('AliOssForTypecho')->endPoint;
return 'https://' . $bucket_name . '.' . $end_point . '.aliyuncs.com/' . $userDir . $content['attachment']->path . $diy_style;
} else {
return $cdnUrl . $userDir . $content['attachment']->path . $diy_style;
2015-09-30 03:26:19 +08:00
}
}
/**
* 获取实际文件数据
*
* @access public
* @param array $content
* @return string
*/
public static function attachmentDataHandle(array $content)
{
return file_get_contents(self::attachmentHandle($content));
2015-09-30 03:26:19 +08:00
}
/**
* 检查文件名
*
* @access private
* @param string $ext 扩展名
* @return boolean
*/
private static function checkFileType($ext)
{
$options = Typecho_Widget::widget('Widget_Options');
return in_array($ext, $options->allowedAttachmentTypes);
}
2020-06-26 19:43:40 +08:00
/**
2015-09-30 03:26:19 +08:00
* 创建上传路径
*
* @access private
* @param string $path 路径
* @return boolean
*/
private static function makeUploadDir($path)
{
$path = preg_replace("/\\\+/", '/', $path);
$current = rtrim($path, '/');
$last = $current;
2020-06-26 19:43:40 +08:00
while (!is_dir($current) && false !== strpos($path, '/')) {
2015-09-30 03:26:19 +08:00
$last = $current;
$current = dirname($current);
}
2020-06-26 19:43:40 +08:00
if ($last == $current) {
2015-09-30 03:26:19 +08:00
return true;
}
2020-06-26 19:43:40 +08:00
if (!@mkdir($last)) {
2015-09-30 03:26:19 +08:00
return false;
}
$stat = @stat($last);
$perms = $stat['mode'] & 0007777;
@chmod($last, $perms);
return self::makeUploadDir($path);
}
/**
* 获取安全的文件名
*
* @param string $name
* @static
* @access private
* @return string
*/
2020-06-26 19:43:40 +08:00
private static function getSafeName(&$name) {
2015-09-30 03:26:19 +08:00
$name = str_replace(array('"', '<', '>'), '', $name);
$name = str_replace('\\', '/', $name);
$name = false === strpos($name, '/') ? ('a' . $name) : str_replace('/', '/a', $name);
$info = pathinfo($name);
$name = substr($info['basename'], 1);
return $name;
}
2020-06-26 19:43:40 +08:00
private static function my_error_log(&$error) {
2020-06-27 14:07:40 +08:00
if (!Typecho_Common::isAppEngine()) {
$upload_root = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
2020-06-26 19:43:40 +08:00
defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__);
2020-06-27 14:07:40 +08:00
$error_log_file = $upload_root . self::LOG_SUFFIX . 'error.log';
2020-06-26 19:43:40 +08:00
2020-06-27 14:07:40 +08:00
$log_dir = dirname($error_log_file);
if (!is_dir($log_dir)) {
if (is_writeable($upload_root)) {
self::makeUploadDir($log_dir);
}
2020-06-26 19:43:40 +08:00
}
2020-06-27 14:07:40 +08:00
if (is_writeable($log_dir)) {
error_log($error, 3, $error_log_file);
}
2020-06-26 19:43:40 +08:00
}
}
private static function getExtentionName(&$name) {
$info = pathinfo($name);
return isset($info['extension']) ? strtolower($info['extension']) : '';
2015-09-30 03:26:19 +08:00
}
2020-06-27 13:49:48 +08:00
2015-09-30 03:26:19 +08:00
}