diff --git a/common.php b/common.php index f7ead28..c0746cd 100644 --- a/common.php +++ b/common.php @@ -198,6 +198,13 @@ function main($path) $url = path_format($_SERVER['PHP_SELF'] . '/'); return output('', 302, [ 'Location' => $url ]); } + if (isset($_GET['WaitFunction'])) { + $response = WaitFunction($_GET['WaitFunction']); + //var_dump($response); + if ($response===true) return output("ok", 200); + elseif ($response===false) return output("", 206); + else return $response; + } $_SERVER['sitename'] = getConfig('sitename'); if (empty($_SERVER['sitename'])) $_SERVER['sitename'] = getconstStr('defaultSitename'); @@ -295,6 +302,7 @@ function main($path) return $drive->bigfileupload($path1); } } + if ($_SERVER['admin']) { $tmp = adminoperate($path); if ($tmp['statusCode'] > 0) { @@ -800,9 +808,9 @@ function get_timezone($timezone = '8') return $timezones[$timezone]; } -function message($message, $title = 'Message', $statusCode = 200) +function message($message, $title = 'Message', $statusCode = 200, $wainstat = 0) { - return output(' + $html = ' @@ -810,14 +818,61 @@ function message($message, $title = 'Message', $statusCode = 200)

' . $title . '

' . getconstStr('Back') . getconstStr('Home') . ' -

+

'; + if ($wainstat) { + $html .= ' +
+ '; + } else { + $html .= ' + '; + } + $html .= ' -', $statusCode); +'; + return output($html, $statusCode); } function needUpdate() @@ -1109,12 +1164,13 @@ function EnvOpt($needUpdate = 0) if (api_error($response)) { $html = api_error_msg($response); $title = 'Error'; + return message($html, $title, 400); } else { //WaitSCFStat(); - $html .= getconstStr('UpdateSuccess') . '
' . getconstStr('Back') . ''; + $html .= getconstStr('UpdateSuccess') . '
' . getconstStr('Back') . ''; $title = getconstStr('Setup'); + return message($html, $title, 202, 1); } - return message($html, $title); } if (isset($_POST['submit1'])) { $_SERVER['disk_oprating'] = ''; @@ -1127,11 +1183,11 @@ function EnvOpt($needUpdate = 0) $f = substr($v, 0, 1); if (strlen($v)==1) $v .= '_'; if (isCommonEnv($v)) { - return message('Do not input ' . $envs . '
' . getconstStr('Back') . '', 'Error', 201); + return message('Do not input ' . $envs . '
' . getconstStr('Back') . '', 'Error', 400); } elseif (!(('a'<=$f && $f<='z') || ('A'<=$f && $f<='Z'))) { - return message('' . getconstStr('Back') . '', 'Please start with letters', 201); + return message('' . getconstStr('Back') . '', 'Please start with letters', 400); } elseif (getConfig($v)) { - return message('' . getconstStr('Back') . '', 'Same tag', 201); + return message('' . getconstStr('Back') . '', 'Same tag', 400); } else { $tmp[$k] = $v; } @@ -1139,7 +1195,7 @@ function EnvOpt($needUpdate = 0) if ($k=='disktag_sort') { $td = implode('|', json_decode($v)); if (strlen($td)==strlen(getConfig('disktag'))) $tmp['disktag'] = $td; - else return message('Something wrong.'); + else return message('Something wrong.', 'ERROR', 400); } if ($k == 'disk') $_SERVER['disk_oprating'] = $v; } @@ -1156,12 +1212,16 @@ function EnvOpt($needUpdate = 0) if (api_error($response)) { $html = api_error_msg($response); $title = 'Error'; + return message($html, $title, 409); } else { $html .= getconstStr('Success') . '!
- ' . getconstStr('Back') . ''; + ' . getconstStr('Back') . ' + '; $title = getconstStr('Setup'); + return message($html, $title, 200, 1); } - return message($html, $title); } if (isset($_POST['config_b'])) { if (!$_POST['pass']) return output("{\"Error\": \"No admin pass\"}", 403); @@ -1233,7 +1293,7 @@ function EnvOpt($needUpdate = 0) if (api_error($response)) { return message(api_error_msg($response) . "" . getconstStr('Back') . "", "Error", 403); } else { - return message("Success" . getconstStr('Back') . "", "Success", 200); + return message("Success" . getconstStr('Back') . "", "Success", 200, 1); } } else { return message("Old pass error" . getconstStr('Back') . "", "Error", 403); diff --git a/conststr.php b/conststr.php index 6e1969b..f3a6dcb 100644 --- a/conststr.php +++ b/conststr.php @@ -1072,11 +1072,11 @@ $constStr = [ 'ar-sa' => 'أكد بي إتش بي قابل للكتابة', ], 'MakesuerRewriteOn' => [ - 'en-us' => 'Plase make sure the RewriteEngine is On.', - 'zh-cn' => '确认重写(伪静态)功能启用。', - 'zh-tw' => '確認重寫(偽靜態)功能啟用。', - 'ja' => '書き換え(擬似静的)機能が有効になっていることを確認します。', - 'ko-kr' => '다시 쓰기 (의사 정적) 기능이 활성화되어 있는지 확인하십시오.', + 'en-us' => 'Plase make sure the RewriteEngine is On', + 'zh-cn' => '确认重写(伪静态)功能启用', + 'zh-tw' => '確認重寫(偽靜態)功能啟用', + 'ja' => '書き換え(擬似静的)機能が有効になっていることを確認します', + 'ko-kr' => '다시 쓰기 (의사 정적) 기능이 활성화되어 있는지 확인하십시오', 'fa' => 'لطفاً مطمئن شوید که RewriteEngine روشن است.', 'ar-sa' => 'يؤكد أن الكتابة يمكن أن تكون وظيفة شبه استاتي', ], diff --git a/disk/Aliyundrive.php b/disk/Aliyundrive.php index 8dfa731..148b375 100644 --- a/disk/Aliyundrive.php +++ b/disk/Aliyundrive.php @@ -629,8 +629,19 @@ class Aliyundrive { $title = 'Error'; return message($html, $title, 201); } else { - $str .= ''; - return message($str, getconstStr('WaitJumpIndex'), 201); + $str .= ' +'; + return message($str, getconstStr('WaitJumpIndex'), 201, 1); } } if (isset($_GET['SelectDrive'])) { @@ -691,17 +702,18 @@ class Aliyundrive { + return true; + } + '; - return message($html, $title, 201); + return message($html, $title, 201, 1); } if (isset($_GET['install0']) && $_POST['disktag_add']!='') { $_POST['disktag_add'] = preg_replace('/[^0-9a-zA-Z|_]/i', '', $_POST['disktag_add']); @@ -737,7 +749,7 @@ class Aliyundrive { if (api_error($response)) { $html = api_error_msg($response); $title = 'Error'; - return message($html, $title, 201); + return message($html, $title, 400); } else { $title = 'Refresh token'; $html = ' @@ -756,9 +768,10 @@ class Aliyundrive { } return true; } + var status = "' . $response['status'] . '"; '; - return message($html, $title, 201); + return message($html, $title, 201, 1); } } diff --git a/disk/Onedrive.php b/disk/Onedrive.php index 426397d..2efcfb8 100644 --- a/disk/Onedrive.php +++ b/disk/Onedrive.php @@ -504,14 +504,23 @@ class Onedrive { $title = 'Error'; return message($html, $title, 201); } else { - $str .= ' - '; - return message($str, getconstStr('WaitJumpIndex'), 201); + return message($html, getconstStr('WaitJumpIndex'), 201, 1); } } @@ -607,9 +616,19 @@ class Onedrive { return message($html, $title, 201); } else { savecache('access_token', $ret['access_token'], $this->disktag, $ret['expires_in'] - 60); - $str .= ' - '; - return message($str, getconstStr('Wait') . ' 3s', 201); + $html .= ''; + return message($html, getconstStr('Wait') . ' 3s', 201, 1); } } return message('
' . json_encode(json_decode($tmp['body']), JSON_PRETTY_PRINT) . '
', $tmp['stat']); @@ -639,7 +658,7 @@ class Onedrive { $f = substr($_POST['disktag_add'], 0, 1); if (strlen($_POST['disktag_add'])==1) $_POST['disktag_add'] .= '_'; if (isCommonEnv($_POST['disktag_add'])) { - return message('Do not input ' . $envs . '
', 'Error', 201); + return message('Do not input ' . $envs . '
', 'Error', 400); } elseif (!(('a'<=$f && $f<='z') || ('A'<=$f && $f<='Z'))) { return message('Please start with letters
', 'Error', 201); + ', 'Error', 400); } $tmp = null; @@ -673,12 +692,26 @@ class Onedrive { if (api_error($response)) { $html = api_error_msg($response); $title = 'Error'; + return message($html, $title, 400); } else { $title = getconstStr('MayinEnv'); - $html = getconstStr('Wait') . ' 3s'; - if ($_POST['Drive_ver']=='Sharelink') $html = getconstStr('Wait') . ' 3s'; + $html = getconstStr('Wait'); + if ($_POST['Drive_ver']!='Sharelink') $url .= '?install1&disktag=' . $_GET['disktag'] . '&AddDisk=' . $_POST['Drive_ver']; + $html .= ''; + return message($html, $title, 201, 1); } - return message($html, $title, 201); + } } diff --git a/index.php b/index.php index f029312..a2d9bd1 100644 --- a/index.php +++ b/index.php @@ -32,7 +32,8 @@ if (isset($_SERVER['USER'])&&$_SERVER['USER']==='qcloud') { http_response_code($re['statusCode']); echo $re['body']; } elseif (isset($_SERVER['DOCUMENT_ROOT'])&&$_SERVER['DOCUMENT_ROOT']==='/var/task/user') { - include 'platform/Vercel.php'; + if (getenv('ONEMANAGER_CONFIG_SAVE')=='env') include 'platform/Vercel_env.php'; + else include 'platform/Vercel.php'; $path = getpath(); //echo 'path:'. $path; $_GET = getGET(); diff --git a/platform/AliyunFC.php b/platform/AliyunFC.php index 2f05deb..ad27a9c 100644 --- a/platform/AliyunFC.php +++ b/platform/AliyunFC.php @@ -497,3 +497,7 @@ function myErrorHandler($errno, $errstr, $errfile, $errline) { } return true; } + +function WaitFunction() { + return true; +} diff --git a/platform/BaiduCFC.php b/platform/BaiduCFC.php index 6fc4db2..e9fbcbb 100644 --- a/platform/BaiduCFC.php +++ b/platform/BaiduCFC.php @@ -431,3 +431,7 @@ function addFileToZip($zip, $rootpath, $path = '') } @closedir($path); } + +function WaitFunction() { + return true; +} diff --git a/platform/Heroku.php b/platform/Heroku.php index d06801e..a096efa 100644 --- a/platform/Heroku.php +++ b/platform/Heroku.php @@ -1,4 +1,5 @@ 'success' ] ); } + +function WaitFunction() { + return true; +} diff --git a/platform/TencentSCF_env.php b/platform/TencentSCF_env.php index c71993c..5bcc2df 100644 --- a/platform/TencentSCF_env.php +++ b/platform/TencentSCF_env.php @@ -371,9 +371,6 @@ function SetbaseConfig($Envs, $function_name, $Region, $Namespace, $SecretId, $S { //echo json_encode($Envs,JSON_PRETTY_PRINT); if ($Envs['ONEMANAGER_CONFIG_SAVE'] == 'file') $Envs = Array( 'ONEMANAGER_CONFIG_SAVE' => 'file' ); - /*$trynum = 0; - while( json_decode(getfunctioninfo($_SERVER['function_name'], $_SERVER['Region'], $_SERVER['namespace'], $SecretId, $SecretKey),true)['Response']['Status']!='Active' ) echo ' -'.++$trynum;*/ //json_decode($a,true)['Response']['Environment']['Variables'][0]['Key'] $tmp = json_decode(getfunctioninfo($function_name, $Region, $Namespace, $SecretId, $SecretKey),true)['Response']['Environment']['Variables']; foreach ($tmp as $tmp1) { @@ -413,7 +410,7 @@ function SetbaseConfig($Envs, $function_name, $Region, $Namespace, $SecretId, $S return post2url('https://'.$host, $data.'&Signature='.urlencode($signStr)); } -function updateProgram($function_name, $Region, $Namespace, $SecretId, $SecretKey, $source) +function updateProgram_OLD($function_name, $Region, $Namespace, $SecretId, $SecretKey, $source) { WaitSCFStat(); $meth = 'POST'; @@ -452,14 +449,158 @@ namespace:' . $_SERVER['namespace'] . '
'; } -function OnekeyUpate($auth = 'qkqpttgf', $project = 'OneManager-php', $branch = 'master') -{ - $source['url'] = 'https://github.com/' . $auth . '/' . $project; - $source['branch'] = $branch; - return updateProgram($_SERVER['function_name'], $_SERVER['Region'], $_SERVER['namespace'], getConfig('SecretId'), getConfig('SecretKey'), $source); -} - function setConfigResponse($response) { return json_decode( $response, true )['Response']; } + +function WaitFunction() { + //$trynum = 0; + //while( json_decode(getfunctioninfo($_SERVER['function_name'], $_SERVER['Region'], $_SERVER['namespace'], getConfig('SecretId'), getConfig('SecretKey')),true)['Response']['Status']!='Active' ) echo ' +//'.++$trynum; + if ( json_decode(getfunctioninfo($_SERVER['function_name'], $_SERVER['Region'], $_SERVER['namespace'], getConfig('SecretId'), getConfig('SecretKey')),true)['Response']['Status']=='Active' ) return true; + else return false; +} + +function updateProgram($function_name, $Region, $Namespace, $SecretId, $SecretKey, $source) +{ + $secretId = $SecretId; + $secretKey = $SecretKey; + $host = 'scf.tencentcloudapi.com'; + $service = "scf"; + $version = "2018-04-16"; + $action = "UpdateFunctionCode"; + $region = $Region; + $timestamp = time(); + $algorithm = "TC3-HMAC-SHA256"; + + // step 1: build canonical request string + $httpRequestMethod = "POST"; + $canonicalUri = "/"; + $canonicalQueryString = ""; + $canonicalHeaders = "content-type:application/json; charset=utf-8\n"."host:".$host."\n"; + $signedHeaders = "content-type;host"; + + //$tmpdata['Action'] = 'UpdateFunctionCode'; + $tmpdata['Code']['ZipFile'] = base64_encode( file_get_contents($source) ); + $tmpdata['CodeSource'] = 'ZipFile'; + $tmpdata['FunctionName'] = $function_name; + $tmpdata['Handler'] = 'index.main_handler'; + //$tmpdata['Namespace'] = $Namespace; + //$tmpdata['Nonce'] = time(); + //$tmpdata['Region'] = $Region; + //$tmpdata['SecretId'] = $SecretId; + //$tmpdata['Timestamp'] = time(); + //$tmpdata['Token'] = ''; + //$tmpdata['Version'] = '2018-04-16'; + $payload = json_encode($tmpdata); + //$payload = '{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}'; + $hashedRequestPayload = hash("SHA256", $payload); + $canonicalRequest = $httpRequestMethod."\n" + .$canonicalUri."\n" + .$canonicalQueryString."\n" + .$canonicalHeaders."\n" + .$signedHeaders."\n" + .$hashedRequestPayload; + //echo $canonicalRequest.PHP_EOL; + + // step 2: build string to sign + $date = gmdate("Y-m-d", $timestamp); + $credentialScope = $date."/".$service."/tc3_request"; + $hashedCanonicalRequest = hash("SHA256", $canonicalRequest); + $stringToSign = $algorithm."\n" + .$timestamp."\n" + .$credentialScope."\n" + .$hashedCanonicalRequest; + //echo $stringToSign.PHP_EOL; + + // step 3: sign string + $secretDate = hash_hmac("SHA256", $date, "TC3".$secretKey, true); + $secretService = hash_hmac("SHA256", $service, $secretDate, true); + $secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true); + $signature = hash_hmac("SHA256", $stringToSign, $secretSigning); + //echo $signature.PHP_EOL; + + // step 4: build authorization + $authorization = $algorithm + ." Credential=".$secretId."/".$credentialScope + .", SignedHeaders=content-type;host, Signature=".$signature; + //echo $authorization.PHP_EOL; + + //$curl = "curl -X POST https://".$host + // .' -H "Authorization: '.$authorization.'"' + // .' -H "Content-Type: application/json; charset=utf-8"' + // .' -H "Host: '.$host.'"' + // .' -H "X-TC-Action: '.$action.'"' + // .' -H "X-TC-Timestamp: '.$timestamp.'"' + // .' -H "X-TC-Version: '.$version.'"' + // .' -H "X-TC-Region: '.$region.'"' + // ." -d '".$payload."'"; + //error_log1( $curl.PHP_EOL ); + //return '{"response": {"Error": {"Message":"' . $curl . '"}}}'; + $headers['Authorization'] = $authorization; + $headers['Content-Type'] = 'application/json; charset=utf-8'; + $headers['Host'] = $host; + $headers['X-TC-Action'] = $action; + $headers['X-TC-Timestamp'] = $timestamp; + $headers['X-TC-Version'] = $version; + $headers['X-TC-Region'] = $region; + return curl('POST', 'https://'.$host, $payload, $headers)['body']; +} + +function OnekeyUpate($auth = 'qkqpttgf', $project = 'OneManager-php', $branch = 'master') +{ + $source = '/tmp/code.zip'; + $outPath = '/tmp/'; + + // 从github下载对应tar.gz,并解压 + $url = 'https://github.com/' . $auth . '/' . $project . '/tarball/' . urlencode($branch) . '/'; + $tarfile = '/tmp/github.tar.gz'; + file_put_contents($tarfile, file_get_contents($url)); + $phar = new PharData($tarfile); + $html = $phar->extractTo($outPath, null, true);//路径 要解压的文件 是否覆盖 + + // 获取包中目录名 + $tmp = scandir('phar://'.$tarfile); + $name = $auth.'-'.$project; + foreach ($tmp as $f) { + if ( substr($f, 0, strlen($name)) == $name) { + $outPath .= $f; + break; + } + } + // 放入配置文件 + file_put_contents($outPath . '/.data/config.php', file_get_contents(__DIR__ . '/../.data/config.php')); + + // 将目录中文件打包成zip + //$zip=new ZipArchive(); + $zip=new PharData($source); + //if($zip->open($source, ZipArchive::CREATE)){ + addFileToZip($zip, $outPath); //调用方法,对要打包的根目录进行操作,并将ZipArchive的对象传递给方法 + // $zip->close(); //关闭处理的zip文件 + //} + + return updateProgram($_SERVER['function_name'], $_SERVER['Region'], $_SERVER['namespace'], getConfig('SecretId'), getConfig('SecretKey'), $source); +} + +function addFileToZip($zip, $rootpath, $path = '') +{ + if (substr($rootpath,-1)=='/') $rootpath = substr($rootpath, 0, -1); + if (substr($path,0,1)=='/') $path = substr($path, 1); + $handler=opendir(path_format($rootpath.'/'.$path)); //打开当前文件夹由$path指定。 + while($filename=readdir($handler)){ + if($filename != "." && $filename != ".."){//文件夹文件名字为'.'和‘..’,不要对他们进行操作 + $nowname = path_format($rootpath.'/'.$path."/".$filename); + if(is_dir($nowname)){// 如果读取的某个对象是文件夹,则递归 + $zip->addEmptyDir($path."/".$filename); + addFileToZip($zip, $rootpath, $path."/".$filename); + }else{ //将文件加入zip对象 + $newname = $path."/".$filename; + if (substr($newname,0,1)=='/') $newname = substr($newname, 1); + $zip->addFile($nowname, $newname); + //$zip->renameName($nowname, $newname); + } + } + } + @closedir($path); +} diff --git a/platform/TencentSCF_file.php b/platform/TencentSCF_file.php index 3ffea06..1a0f256 100644 --- a/platform/TencentSCF_file.php +++ b/platform/TencentSCF_file.php @@ -645,3 +645,8 @@ function addFileToZip($zip, $rootpath, $path = '') } @closedir($path); } + +function WaitFunction() { + if ( json_decode(getfunctioninfo($_SERVER['function_name'], $_SERVER['Region'], $_SERVER['namespace'], getConfig('SecretId'), getConfig('SecretKey')),true)['Response']['Status']=='Active' ) return true; + else return false; +} diff --git a/platform/Vercel.php b/platform/Vercel.php index 3f38087..c6f7b59 100644 --- a/platform/Vercel.php +++ b/platform/Vercel.php @@ -67,18 +67,24 @@ function getGET() function getConfig($str, $disktag = '') { - if (isInnerEnv($str)) { - if ($disktag=='') $disktag = $_SERVER['disktag']; - $tmp = getenv($disktag); - if (is_array($tmp)) $env = $tmp; - else $env = json_decode($tmp, true); - if (isset($env[$str])) { - if (isBase64Env($str)) return base64y_decode($env[$str]); - else return $env[$str]; - } - } else { - if (isBase64Env($str)) return base64y_decode(getenv($str)); - else return getenv($str); + $projectPath = splitlast(__DIR__, '/')[0]; + $configPath = $projectPath . '/.data/config.php'; + $s = file_get_contents($configPath); + $configs = '{' . splitlast(splitfirst($s, '{')[1], '}')[0] . '}'; + if ($configs!='') { + $envs = json_decode($configs, true); + if (isInnerEnv($str)) { + if ($disktag=='') $disktag = $_SERVER['disktag']; + if (isset($envs[$disktag][$str])) { + if (isBase64Env($str)) return base64y_decode($envs[$disktag][$str]); + else return $envs[$disktag][$str]; + } + } else { + if (isset($envs[$str])) { + if (isBase64Env($str)) return base64y_decode($envs[$str]); + else return $envs[$str]; + } + } } return ''; } @@ -86,45 +92,45 @@ function getConfig($str, $disktag = '') function setConfig($arr, $disktag = '') { if ($disktag=='') $disktag = $_SERVER['disktag']; - $disktags = explode("|", getenv('disktag')); - if ($disktag!='') { - $tmp = getenv($disktag); - if (is_array($tmp)) $diskconfig = $tmp; - else $diskconfig = json_decode($tmp, true); - } - $tmp = []; + $projectPath = splitlast(__DIR__, '/')[0]; + $configPath = $projectPath . '/.data/config.php'; + $s = file_get_contents($configPath); + $configs = '{' . splitlast(splitfirst($s, '{')[1], '}')[0] . '}'; + if ($configs!='') $envs = json_decode($configs, true); + $disktags = explode("|",getConfig('disktag')); $indisk = 0; $operatedisk = 0; foreach ($arr as $k => $v) { if (isCommonEnv($k)) { - if (isBase64Env($k)) $tmp[$k] = base64y_encode($v); - else $tmp[$k] = $v; + if (isBase64Env($k)) $envs[$k] = base64y_encode($v); + else $envs[$k] = $v; } elseif (isInnerEnv($k)) { - if (isBase64Env($k)) $diskconfig[$k] = base64y_encode($v); - else $diskconfig[$k] = $v; + if (isBase64Env($k)) $envs[$disktag][$k] = base64y_encode($v); + else $envs[$disktag][$k] = $v; $indisk = 1; } elseif ($k=='disktag_add') { array_push($disktags, $v); $operatedisk = 1; } elseif ($k=='disktag_del') { $disktags = array_diff($disktags, [ $v ]); - $tmp[$v] = ''; + $envs[$v] = ''; $operatedisk = 1; } elseif ($k=='disktag_copy') { $newtag = $v . '_' . date("Ymd_His"); - $tmp[$newtag] = getConfig($v); + $envs[$newtag] = $envs[$v]; array_push($disktags, $newtag); $operatedisk = 1; } elseif ($k=='disktag_rename' || $k=='disktag_newname') { if ($arr['disktag_rename']!=$arr['disktag_newname']) $operatedisk = 1; } else { - $tmp[$k] = json_encode($v); + $envs[$k] = $v; } } if ($indisk) { + $diskconfig = $envs[$disktag]; $diskconfig = array_filter($diskconfig, 'array_value_isnot_null'); ksort($diskconfig); - $tmp[$disktag] = json_encode($diskconfig); + $envs[$disktag] = $diskconfig; } if ($operatedisk) { if (isset($arr['disktag_newname']) && $arr['disktag_newname']!='') { @@ -133,20 +139,21 @@ function setConfig($arr, $disktag = '') if ($tag==$arr['disktag_rename']) array_push($tags, $arr['disktag_newname']); else array_push($tags, $tag); } - $tmp['disktag'] = implode('|', $tags); - $tmp[$arr['disktag_newname']] = getConfig($arr['disktag_rename']); - $tmp[$arr['disktag_rename']] = null; + $envs['disktag'] = implode('|', $tags); + $envs[$arr['disktag_newname']] = $envs[$arr['disktag_rename']]; + $envs[$arr['disktag_rename']] = ''; } else { $disktags = array_unique($disktags); foreach ($disktags as $disktag) if ($disktag!='') $disktag_s .= $disktag . '|'; - if ($disktag_s!='') $tmp['disktag'] = substr($disktag_s, 0, -1); - else $tmp['disktag'] = null; + if ($disktag_s!='') $envs['disktag'] = substr($disktag_s, 0, -1); + else $envs['disktag'] = ''; } } - foreach ($tmp as $key => $val) if ($val=='') $tmp[$key]=null; - - return setVercelConfig($tmp, getConfig('HerokuappId'), getConfig('APIKey')); - error_log1(json_encode($arr, JSON_PRETTY_PRINT) . ' => tmp:' . json_encode($tmp, JSON_PRETTY_PRINT)); + $envs = array_filter($envs, 'array_value_isnot_null'); + //ksort($envs); + //error_log1(json_encode($arr, JSON_PRETTY_PRINT) . ' => tmp:' . json_encode($envs, JSON_PRETTY_PRINT)); + //echo json_encode($arr, JSON_PRETTY_PRINT) . ' => tmp:' . json_encode($envs, JSON_PRETTY_PRINT); + return setVercelConfig($envs, getConfig('HerokuappId'), getConfig('APIKey')); } function install() @@ -157,49 +164,39 @@ function install() $tmp['admin'] = $_POST['admin']; //$tmp['language'] = $_POST['language']; $tmp['timezone'] = $_COOKIE['timezone']; - $APIKey = getConfig('APIKey'); - if ($APIKey=='') { - $APIKey = $_POST['APIKey']; - $tmp['APIKey'] = $APIKey; - } - - $projectPath = splitlast(__DIR__, "/")[0]; - //$html .= file_get_contents($projectPath . "/.data/config.php") . "
";GET /v5/now/deployments /v8/projects/:id/env - $token = $tmp['APIKey']; - $header["Authorization"] = "Bearer " . $token; - $header["Content-Type"] = "application/json"; - $aliases = json_decode(curl("GET", "https://api.vercel.com/v3/now/aliases", "", $header)['body'], true); - $host = splitfirst($_SERVER["host"], "//")[1]; - foreach ($aliases["aliases"] as $key => $aliase) { - if ($host==$aliase["alias"]) $projectId = $aliase["projectId"]; - } - //$envs = json_decode(curl("GET", "https://api.vercel.com/v8/projects/" . $projectId . "/env", "", $header)['body'], true); + $APIKey = $_POST['APIKey']; + //if ($APIKey=='') { + // $APIKey = getConfig('APIKey'); + //} + $tmp['APIKey'] = $APIKey; + $token = $APIKey; + $header["Authorization"] = "Bearer " . $token; + $header["Content-Type"] = "application/json"; + $aliases = json_decode(curl("GET", "https://api.vercel.com/v3/now/aliases", "", $header)['body'], true); + $host = splitfirst($_SERVER["host"], "//")[1]; + foreach ($aliases["aliases"] as $key => $aliase) { + if ($host==$aliase["alias"]) $projectId = $aliase["projectId"]; + } $tmp['HerokuappId'] = $projectId; - $response = json_decode(setVercelConfig($tmp, $projectId, $APIKey)['body'], true); + + $response = json_decode(setVercelConfig($tmp, $projectId, $APIKey), true); if (api_error($response)) { $html = api_error_msg($response); $title = 'Error'; + return message($html, $title, 400); } else { - return output(' - - ', 302); + '; + return message($html, $title, 201, 1);*/ + $data["dplId"] = $response['status']; + return output(json_encode($data), 201); } - return message($html, $title, 201); } } if ($_GET['install0']) { @@ -210,14 +207,16 @@ language:
'; $html .= '
'; } - if (getConfig('APIKey')=='') $html .= ' + //if (getConfig('APIKey')=='') + $html .= '
' . getconstStr('Create') . ' token
-
'; +
'; $html .= '

'; $html .= ' +
'; $title = getconstStr('SelectLanguage'); return message($html, $title, 201); } - if (substr($_SERVER["host"], -10)=="vercel.app") { - $html .= '' . getconstStr('ClickInstall') . ', ' . getconstStr('LogintoBind'); - $html .= "
Remember: you MUST wait 30-60s after each operate / do some change, that make sure Vercel has done the building
" ; - } else { - $html.= "Please visit form *.vercel.app"; - } + if (substr($_SERVER["host"], -10)=="vercel.app") { + $html .= '' . getconstStr('ClickInstall') . ', ' . getconstStr('LogintoBind'); + $html .= "
Remember: you MUST wait 30-60s after each operate / do some change, that make sure Vercel has done the building
" ; + } else { + $html.= "Please visit form *.vercel.app"; + } $title = 'Install'; return message($html, $title, 201); } -// POST /v8/projects/:id/env +function copyFolder($from, $to) +{ + if (substr($from, -1)=='/') $from = substr($from, 0, -1); + if (substr($to, -1)=='/') $to = substr($to, 0, -1); + if (!file_exists($to)) mkdir($to, 0777, 1); + $handler=opendir($from); + while($filename=readdir($handler)) { + if($filename != '.' && $filename != '..'){ + $fromfile = $from.'/'.$filename; + $tofile = $to.'/'.$filename; + if(is_dir($fromfile)){// 如果读取的某个对象是文件夹,则递归 + copyFolder($fromfile, $tofile); + }else{ + copy($fromfile, $tofile); + } + } + } + closedir($handler); + return 1; +} + function setVercelConfig($envs, $appId, $token) { - $url = "https://api.vercel.com/v8/projects/" . $appId . "/env"; - $header["Authorization"] = "Bearer " . $token; - $header["Content-Type"] = "application/json"; - $response = curl("GET", $url, "", $header); - $result = json_decode($response['body'], true); - foreach ($result["envs"] as $key => $value) { - $existEnvs[$value["key"]] = $value["id"]; - } - $response = null; - foreach ($envs as $key => $value) { - $tmp = null; - $tmp["type"] = "encrypted"; - $tmp["key"] = $key; - $tmp["value"] = $value; - $tmp["target"] = [ "development", "production", "preview" ]; - if (isset($existEnvs[$key])) { - if ($value) $response = curl("PATCH", $url . "/" . $existEnvs[$key], json_encode($tmp), $header); - else $response = curl("DELETE", $url . "/" . $existEnvs[$key], "", $header); - } else { - if ($value) $response = curl("POST", $url, json_encode($tmp), $header); - } - //echo $key . ":" . $value . ", " . json_encode($response, JSON_PRETTY_PRINT) . "
"; - } - return VercelUpdate($appId, $token); - //return $response; + //sortConfig($envs); cant view in vercel, not need sort. + $outPath = '/tmp/code/'; + $outPath_Api = $outPath . 'api/'; + $coderoot = __DIR__; + $coderoot = splitlast($coderoot, '/')[0] . '/'; + //echo $outPath_Api . '
' . $coderoot . '
'; + copyFolder($coderoot, $outPath_Api); + $prestr = '"; - getEachFiles($file, $sourcePath); - $data["files"] = $file; + $url = "https://api.vercel.com/v12/now/deployments"; + $header["Authorization"] = "Bearer " . $token; + $header["Content-Type"] = "application/json"; + $data["name"] = "OneManager"; + $data["project"] = $appId; + $data["target"] = "production"; + $data["routes"][0]["src"] = "/(.*)"; + $data["routes"][0]["dest"] = "/api/index.php"; + $data["functions"]["api/index.php"]["runtime"] = "vercel-php@0.4.0"; + if ($sourcePath=="") $sourcePath = splitlast(splitlast(__DIR__, "/")[0], "/")[0]; + //echo $sourcePath . "
"; + getEachFiles($file, $sourcePath); + $data["files"] = $file; - //echo json_encode($data, JSON_PRETTY_PRINT) . " ,data
"; - $response = curl("POST", $url, json_encode($data), $header); - return $response["body"]; + //echo json_encode($data, JSON_PRETTY_PRINT) . " ,data
"; + $response = curl("POST", $url, json_encode($data), $header); + //echo json_encode($response, JSON_PRETTY_PRINT) . " ,res
"; + $result = json_decode($response["body"], true); + $result['status'] = $result['id']; + return json_encode($result); } function getEachFiles(&$file, $base, $path = "") @@ -321,13 +374,13 @@ function getEachFiles(&$file, $base, $path = "") while($filename=readdir($handler)) { if($filename != '.' && $filename != '..' && $filename != '.git'){ $fromfile = path_format($base . "/" . $path . "/" . $filename); - //echo $fromfile . "
"; + //echo $fromfile . "
"; if(is_dir($fromfile)){// 如果读取的某个对象是文件夹,则递归 $response = getEachFiles($file, $base, path_format($path . "/" . $filename)); if (api_error(setConfigResponse($response))) return $response; }else{ - $tmp['file'] = path_format($path . "/" . $filename); - $tmp['data'] = file_get_contents($fromfile); + $tmp['file'] = path_format($path . "/" . $filename); + $tmp['data'] = file_get_contents($fromfile); $file[] = $tmp; } } @@ -371,7 +424,7 @@ function OnekeyUpate($auth = 'qkqpttgf', $project = 'OneManager-php', $branch = $outPath = ''; $tmp = scandir($tmppath); $name = $auth . '-' . $project; - mkdir($tmppath . "/" . $name, 0777); + mkdir($tmppath . "/" . $name, 0777, 1); foreach ($tmp as $f) { if ( substr($f, 0, strlen($name)) == $name) { rename($tmppath . '/' . $f, $tmppath . "/" . $name . '/api'); @@ -379,9 +432,30 @@ function OnekeyUpate($auth = 'qkqpttgf', $project = 'OneManager-php', $branch = break; } } - //echo $outPath . "
"; + //echo $outPath . "
"; //error_log1($outPath); if ($outPath=='') return '{"error":{"message":"no outpath"}}'; + // put in config + $coderoot = __DIR__; + $coderoot = splitlast($coderoot, '/')[0] . '/'; + copy($coderoot . '.data/config.php', $outPath . '/api/.data/config.php'); + return VercelUpdate(getConfig('HerokuappId'), getConfig('APIKey'), $outPath); } + +function WaitFunction($deployid) { + $header["Authorization"] = "Bearer " . getConfig('APIKey'); + $header["Content-Type"] = "application/json"; + $url = "https://api.vercel.com/v11/now/deployments/" . $deployid; + $response = curl("GET", $url, "", $header); + if ($response['stat']==200) { + $result = json_decode($response['body'], true); + if ($result['readyState']=="READY") return true; + if ($result['readyState']=="ERROR") return $response; + return false; + } else { + $response['body'] .= $url; + return $response; + } +} diff --git a/platform/Vercel_env.php b/platform/Vercel_env.php new file mode 100644 index 0000000..5f440af --- /dev/null +++ b/platform/Vercel_env.php @@ -0,0 +1,447 @@ +0) $path = substr($_SERVER['REQUEST_URI'], 0, $p); + else $path = $_SERVER['REQUEST_URI']; + $path = path_format( substr($path, strlen($_SERVER['base_path'])) ); + $_SERVER['DOCUMENT_ROOT'] = '/var/task/user'; + return $path; +} + +function getGET() +{ + if (!$_POST) { + if (!!$HTTP_RAW_POST_DATA) { + $tmpdata = $HTTP_RAW_POST_DATA; + } else { + $tmpdata = file_get_contents('php://input'); + } + if (!!$tmpdata) { + $postbody = explode("&", $tmpdata); + foreach ($postbody as $postvalues) { + $pos = strpos($postvalues,"="); + $_POST[urldecode(substr($postvalues,0,$pos))]=urldecode(substr($postvalues,$pos+1)); + } + } + } + if (isset($_SERVER['UNENCODED_URL'])) $_SERVER['REQUEST_URI'] = $_SERVER['UNENCODED_URL']; + $p = strpos($_SERVER['REQUEST_URI'],'?'); + if ($p>0) { + $getstr = substr($_SERVER['REQUEST_URI'], $p+1); + $getstrarr = explode("&",$getstr); + foreach ($getstrarr as $getvalues) { + if ($getvalues != '') { + $pos = strpos($getvalues, "="); + //echo $pos; + if ($pos > 0) { + $getarry[urldecode(substr($getvalues, 0, $pos))] = urldecode(substr($getvalues, $pos + 1)); + } else { + $getarry[urldecode($getvalues)] = true; + } + } + } + } + if (isset($getarry)) { + return $getarry; + } else { + return []; + } +} + +function getConfig($str, $disktag = '') +{ + if (isInnerEnv($str)) { + if ($disktag=='') $disktag = $_SERVER['disktag']; + $tmp = getenv($disktag); + if (is_array($tmp)) $env = $tmp; + else $env = json_decode($tmp, true); + if (isset($env[$str])) { + if (isBase64Env($str)) return base64y_decode($env[$str]); + else return $env[$str]; + } + } else { + if (isBase64Env($str)) return base64y_decode(getenv($str)); + else return getenv($str); + } + return ''; +} + +function setConfig($arr, $disktag = '') +{ + if ($disktag=='') $disktag = $_SERVER['disktag']; + $disktags = explode("|", getenv('disktag')); + if ($disktag!='') { + $tmp = getenv($disktag); + if (is_array($tmp)) $diskconfig = $tmp; + else $diskconfig = json_decode($tmp, true); + } + $tmp = []; + $indisk = 0; + $operatedisk = 0; + foreach ($arr as $k => $v) { + if (isCommonEnv($k)) { + if (isBase64Env($k)) $tmp[$k] = base64y_encode($v); + else $tmp[$k] = $v; + } elseif (isInnerEnv($k)) { + if (isBase64Env($k)) $diskconfig[$k] = base64y_encode($v); + else $diskconfig[$k] = $v; + $indisk = 1; + } elseif ($k=='disktag_add') { + array_push($disktags, $v); + $operatedisk = 1; + } elseif ($k=='disktag_del') { + $disktags = array_diff($disktags, [ $v ]); + $tmp[$v] = ''; + $operatedisk = 1; + } elseif ($k=='disktag_copy') { + $newtag = $v . '_' . date("Ymd_His"); + $tagvalue = getenv($v); + if (is_array($tagvalue)) $tmp[$newtag] = json_encode($tagvalue); + else $tmp[$newtag] = $tagvalue; + array_push($disktags, $newtag); + $operatedisk = 1; + } elseif ($k=='disktag_rename' || $k=='disktag_newname') { + if ($arr['disktag_rename']!=$arr['disktag_newname']) $operatedisk = 1; + } else { + $tmp[$k] = json_encode($v); + } + } + if ($indisk) { + $diskconfig = array_filter($diskconfig, 'array_value_isnot_null'); + ksort($diskconfig); + $tmp[$disktag] = json_encode($diskconfig); + } + if ($operatedisk) { + if (isset($arr['disktag_newname']) && $arr['disktag_newname']!='') { + $tags = []; + foreach ($disktags as $tag) { + if ($tag==$arr['disktag_rename']) array_push($tags, $arr['disktag_newname']); + else array_push($tags, $tag); + } + $tmp['disktag'] = implode('|', $tags); + $tagvalue = getenv($arr['disktag_rename']); + if (is_array($tagvalue)) $tmp[$arr['disktag_newname']] = json_encode($tagvalue); + else $tmp[$arr['disktag_newname']] = $tagvalue; + $tmp[$arr['disktag_rename']] = null; + } else { + $disktags = array_unique($disktags); + foreach ($disktags as $disktag) if ($disktag!='') $disktag_s .= $disktag . '|'; + if ($disktag_s!='') $tmp['disktag'] = substr($disktag_s, 0, -1); + else $tmp['disktag'] = null; + } + } + foreach ($tmp as $key => $val) if ($val=='') $tmp[$key]=null; + + //error_log1(json_encode($arr, JSON_PRETTY_PRINT) . ' => tmp:' . json_encode($tmp, JSON_PRETTY_PRINT)); + //echo json_encode($arr, JSON_PRETTY_PRINT) . ' => tmp:' . json_encode($tmp, JSON_PRETTY_PRINT); + return setVercelConfig($tmp, getConfig('HerokuappId'), getConfig('APIKey')); +} + +function install() +{ + global $constStr; + if ($_GET['install1']) { + if ($_POST['admin']!='') { + $tmp['admin'] = $_POST['admin']; + //$tmp['language'] = $_POST['language']; + $tmp['timezone'] = $_COOKIE['timezone']; + $APIKey = $_POST['APIKey']; + //if ($APIKey=='') { + // $APIKey = getConfig('APIKey'); + //} + $tmp['APIKey'] = $APIKey; + + $token = $APIKey; + $header["Authorization"] = "Bearer " . $token; + $header["Content-Type"] = "application/json"; + $aliases = json_decode(curl("GET", "https://api.vercel.com/v3/now/aliases", "", $header)['body'], true); + $host = splitfirst($_SERVER["host"], "//")[1]; + foreach ($aliases["aliases"] as $key => $aliase) { + if ($host==$aliase["alias"]) $projectId = $aliase["projectId"]; + } + $tmp['HerokuappId'] = $projectId; + + $response = json_decode(setVercelConfig($tmp, $projectId, $APIKey), true); + if (api_error($response)) { + $html = api_error_msg($response); + $title = 'Error'; + return message($html, $title, 400); + } else { + /*$html = ''; + return message($html, $title, 201, 1);*/ + $data["dplId"] = $response['status']; + return output(json_encode($data), 201); + } + } + } + if ($_GET['install0']) { + $html .= ' +
+language:
'; + foreach ($constStr['languages'] as $key1 => $value1) { + $html .= ' +
'; + } + //if (getConfig('APIKey')=='') + $html .= '
+ ' . getconstStr('Create') . ' token
+
'; + $html .= '
+
'; + $html .= ' + +
+
+ '; + $title = getconstStr('SelectLanguage'); + return message($html, $title, 201); + } + + if (substr($_SERVER["host"], -10)=="vercel.app") { + $html .= '' . getconstStr('ClickInstall') . ', ' . getconstStr('LogintoBind'); + $html .= "
Remember: you MUST wait 30-60s after each operate / do some change, that make sure Vercel has done the building
" ; + } else { + $html.= "Please visit form *.vercel.app"; + } + $title = 'Install'; + return message($html, $title, 201); +} + +// POST /v8/projects/:id/env +function setVercelConfig($envs, $appId, $token) +{ + $url = "https://api.vercel.com/v8/projects/" . $appId . "/env"; + $header["Authorization"] = "Bearer " . $token; + $header["Content-Type"] = "application/json"; + $response = curl("GET", $url, "", $header); + $result = json_decode($response['body'], true); + foreach ($result["envs"] as $key => $value) { + $existEnvs[$value["key"]] = $value["id"]; + } + foreach ($envs as $key => $value) { + $response = null; + $tmp = null; + $tmp["type"] = "encrypted"; + $tmp["key"] = $key; + $tmp["value"] = $value; + $tmp["target"] = [ "development", "production", "preview" ]; + if (isset($existEnvs[$key])) { + if ($value) $response = curl("PATCH", $url . "/" . $existEnvs[$key], json_encode($tmp), $header); + else $response = curl("DELETE", $url . "/" . $existEnvs[$key], "", $header); + } else { + if ($value) $response = curl("POST", $url, json_encode($tmp), $header); + } + //echo $key . " = " . $value . ",
" . $response . json_encode($response, JSON_PRETTY_PRINT) . "
"; + if (!!$response && $response['stat']!=200) return $response['body']; + } + return VercelUpdate($appId, $token); +} + +function VercelUpdate($appId, $token, $sourcePath = "") +{ + $url = "https://api.vercel.com/v12/now/deployments"; + $header["Authorization"] = "Bearer " . $token; + $header["Content-Type"] = "application/json"; + $data["name"] = "OneManager"; + $data["project"] = $appId; + $data["target"] = "production"; + $data["routes"][0]["src"] = "/(.*)"; + $data["routes"][0]["dest"] = "/api/index.php"; + $data["functions"]["api/index.php"]["runtime"] = "vercel-php@0.4.0"; + if ($sourcePath=="") $sourcePath = splitlast(splitlast(__DIR__, "/")[0], "/")[0]; + //echo $sourcePath . "
"; + getEachFiles($file, $sourcePath); + $data["files"] = $file; + + //echo json_encode($data, JSON_PRETTY_PRINT) . " ,data
"; + $response = curl("POST", $url, json_encode($data), $header); + //echo json_encode($response, JSON_PRETTY_PRINT) . " ,res
"; + $result = json_decode($response["body"], true); + $result['status'] = $result['id']; + return json_encode($result); +} + +function getEachFiles(&$file, $base, $path = "") +{ + //if (substr($base, -1)=="/") $base = substr($base, 0, -1); + //if (substr($path, -1)=="/") $path = substr($path, 0, -1); + $handler=opendir(path_format($base . "/" . $path)); + while($filename=readdir($handler)) { + if($filename != '.' && $filename != '..' && $filename != '.git'){ + $fromfile = path_format($base . "/" . $path . "/" . $filename); + //echo $fromfile . "
"; + if(is_dir($fromfile)){// 如果读取的某个对象是文件夹,则递归 + $response = getEachFiles($file, $base, path_format($path . "/" . $filename)); + if (api_error(setConfigResponse($response))) return $response; + }else{ + $tmp['file'] = path_format($path . "/" . $filename); + $tmp['data'] = file_get_contents($fromfile); + $file[] = $tmp; + } + } + } + closedir($handler); + + return json_encode( [ 'response' => 'success' ] ); +} + +function api_error($response) +{ + return isset($response['error']); +} + +function api_error_msg($response) +{ + return $response['error']['code'] . '
+' . $response['error']['message'] . '
+'; +} + +function setConfigResponse($response) +{ + return json_decode($response, true); +} + +function OnekeyUpate($auth = 'qkqpttgf', $project = 'OneManager-php', $branch = 'master') +{ + $tmppath = '/tmp'; + + // 从github下载对应tar.gz,并解压 + $url = 'https://github.com/' . $auth . '/' . $project . '/tarball/' . urlencode($branch) . '/'; + $tarfile = $tmppath . '/github.tar.gz'; + $githubfile = file_get_contents($url); + if (!$githubfile) return '{"error":{"message":"fail to download from github"}}'; + file_put_contents($tarfile, $githubfile); + $phar = new PharData($tarfile); // need php5.3, 7, 8 + $phar->extractTo($tmppath, null, true);//路径 要解压的文件 是否覆盖 + unlink($tarfile); + + $outPath = ''; + $tmp = scandir($tmppath); + $name = $auth . '-' . $project; + mkdir($tmppath . "/" . $name, 0777); + foreach ($tmp as $f) { + if ( substr($f, 0, strlen($name)) == $name) { + rename($tmppath . '/' . $f, $tmppath . "/" . $name . '/api'); + $outPath = $tmppath . "/" . $name; + break; + } + } + //echo $outPath . "
"; + //error_log1($outPath); + if ($outPath=='') return '{"error":{"message":"no outpath"}}'; + + return VercelUpdate(getConfig('HerokuappId'), getConfig('APIKey'), $outPath); +} + +function WaitFunction($deployid) { + $header["Authorization"] = "Bearer " . getConfig('APIKey'); + $header["Content-Type"] = "application/json"; + $url = "https://api.vercel.com/v11/now/deployments/" . $deployid; + $response = curl("GET", $url, "", $header); + if ($response['stat']==200) { + $result = json_decode($response['body'], true); + if ($result['readyState']=="READY") return true; + if ($result['readyState']=="ERROR") return $response; + return false; + } else { + $response['body'] .= $url; + return $response; + } +} diff --git a/readme.md b/readme.md index 5dd2166..80b2778 100644 --- a/readme.md +++ b/readme.md @@ -8,7 +8,7 @@ Official: https://heroku.com Demo: https://herooneindex.herokuapp.com/ How to Install: -> ~~Click the button [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/qkqpttgf/OneManager-php) to Deploy a new app~~(`"We couldn't deploy your app because the source code violates the Salesforce Acceptable Use and External-Facing Services Policy."`) +> ~~Click the button [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) to Deploy a new app~~(`"We couldn't deploy your app because the source code violates the Salesforce Acceptable Use and External-Facing Services Policy."`) > Fork this project, create a heroku app, then turn to Deploy tab, deploy via connect to your github fork. @@ -24,8 +24,7 @@ Official: https://vercel.com/ Demo: null Notice: > 1, you must wait 30-50s to make sure deploy READY after change config; -> 2, the max size of environment is 4k, so you can add 3 onedrive or less; -> 3, Vercel limit 100 deploy every day. +> 2, Vercel limit 100 deploy every day. How to Install: https://scfonedrive.github.io/Vercel/Deploy.html . @@ -130,7 +129,7 @@ it will showed at top or bottom as markdown. 以MD语法显示在顶部或底部 it will showed at top or bottom as html (javascript works!). 以html显示在顶部或底部(可以跑js)。 # A cup of coffee -paypal.me/qkqpttgf +https://paypal.me/qkqpttgf # Chat QQ Group: 212088653 (请看完上面的中英双语再加群,谢谢!) diff --git a/version b/version index ef685bd..8241a53 100644 --- a/version +++ b/version @@ -1,7 +1,13 @@ +20210820-1810.40 +because Vercel must redeploy after change Environment Variables, and it must <4k, so decide that, save config in code file. in Vercel, after update, please install again. if you want continue use Environment, please add a ( name: "ONEMANAGER_CONFIG_SAVE", value: "env" ) in Environment Variables in Project Settings before update. +因为Vercel修改环境变量也必须重新部署才生效,而且环境变量只能小于4k,所以决定将配置保存在代码文件中。升级更新后,用Vercel的请重新安装。如果还想继续使用环境变量,请在更新前,在Project Settings的Environment Variables中,新增一个( name: "ONEMANAGER_CONFIG_SAVE", value: "env" )的环境变量。 + +20210817-2030.39 +fix bugs in Vercel. add wait function in operating. change update method in SCF. add payme in readme. +修复一些Vercel上的bug。在操作完后添加等待功能,确认平台已经准备好。SCF的更新方式改变。在readme中添加讨饭链接。 20210804-1535.38 try fix "&"/"&" in filename. try show an img too height. change upload chunk size when upload speed>10M/s. fix forceHttps when custom domain in Glitch. fix ionicons svg lost.try use file id when rename. background (or other) based on width/height not only width. fix some bugs. Pre-Add platform Vercel, just wait bugs fixed. 尝试修复文件名含 "&"/"&"。尝试在一屏内显示过长的图片。上传时分割的块大小随着上传速度改变。修复Glitch中使用自定义域名时forceHttps问题。修复ionicons图标失踪。尝试在重命名时使用file id来操作。背景(或其它)基于长宽来看是竖屏还是横屏,不再只看宽度。修复其它bug。预加入Vercel平台,等修复bugs。 - 20210512-1648.37 add setting "forceHttps", can force 302 jump to https. fix preview office files. fix manage in safari.fix disktag can be "home". fix some bugs. 新增一个设置,可以强制跳转https。修复office文档预览。修复safari上点不了管理。盘的标签可以是home了,随便命名了。修复一些其它问题。