6881 changed files with 940 additions and 771699 deletions
@ -1,8 +0,0 @@ |
|||||
# api请求地址 |
|
||||
VITE_APP_BASE_URL='/adminapi/' |
|
||||
|
|
||||
# 图片服务器地址 |
|
||||
VITE_IMG_DOMAIN='' |
|
||||
|
|
||||
# 请求时header中token的参数名 |
|
||||
VITE_REQUEST_HEADER_TOKEN_KEY='token' |
|
||||
@ -1,8 +0,0 @@ |
|||||
# api请求地址 |
|
||||
VITE_APP_BASE_URL='/adminapi/' |
|
||||
|
|
||||
# 图片服务器地址 |
|
||||
VITE_IMG_DOMAIN='' |
|
||||
|
|
||||
# 请求时header中token的参数名 |
|
||||
VITE_REQUEST_HEADER_TOKEN_KEY='token' |
|
||||
@ -1,5 +1,5 @@ |
|||||
// Generated by 'unplugin-auto-import'
|
// Generated by 'unplugin-auto-import'
|
||||
export {} |
export {} |
||||
declare global { |
declare global { |
||||
const ElNotification: typeof import('element-plus/es')['ElNotification'] |
|
||||
} |
} |
||||
|
|||||
@ -0,0 +1,52 @@ |
|||||
|
import request from '@/utils/request' |
||||
|
|
||||
|
// USER_CODE_BEGIN -- campus
|
||||
|
/** |
||||
|
* 获取校区列表 |
||||
|
* @param params |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function getCampusList(params: Record<string, any>) { |
||||
|
return request.get(`campus/campus`, {params}) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取校区详情 |
||||
|
* @param id 校区id |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function getCampusInfo(id: number) { |
||||
|
return request.get(`campus/campus/${id}`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加校区 |
||||
|
* @param params |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function addCampus(params: Record<string, any>) { |
||||
|
return request.post('campus/campus', params, { showErrorMessage: true, showSuccessMessage: true }) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 编辑校区 |
||||
|
* @param id |
||||
|
* @param params |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function editCampus(params: Record<string, any>) { |
||||
|
return request.put(`campus/campus/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true }) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除校区 |
||||
|
* @param id |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function deleteCampus(id: number) { |
||||
|
return request.delete(`campus/campus/${id}`, { showErrorMessage: true, showSuccessMessage: true }) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
// USER_CODE_END -- campus
|
||||
@ -0,0 +1,27 @@ |
|||||
|
{ |
||||
|
"id":"主键ID", |
||||
|
"idPlaceholder":"请输入主键ID", |
||||
|
"campusName":"校区名称", |
||||
|
"campusNamePlaceholder":"请输入校区名称", |
||||
|
"campusAddress":"校区地址", |
||||
|
"campusAddressPlaceholder":"请输入校区地址", |
||||
|
"campusPreviewImage":"校区预览图,存储图片路径", |
||||
|
"campusPreviewImagePlaceholder":"请输入校区预览图,存储图片路径", |
||||
|
"campusCoordinates":"校区坐标,格式为经度,纬度", |
||||
|
"campusCoordinatesPlaceholder":"请输入校区坐标,格式为经度,纬度", |
||||
|
"campusIntroduction":"校区介绍", |
||||
|
"campusIntroductionPlaceholder":"请输入校区介绍", |
||||
|
"campusStatus":"校区状态:0-禁用,1-启用", |
||||
|
"campusStatusPlaceholder":"请输入校区状态:0-禁用,1-启用", |
||||
|
"createTime":"校区创建时间", |
||||
|
"createTimePlaceholder":"请输入校区创建时间", |
||||
|
"updateTime":"校区更新时间", |
||||
|
"updateTimePlaceholder":"请输入校区更新时间", |
||||
|
"deleteTime":"逻辑删除字段,NULL表示未删除,非空表示已删除", |
||||
|
"deleteTimePlaceholder":"请输入逻辑删除字段,NULL表示未删除,非空表示已删除", |
||||
|
"addCampus":"添加校区", |
||||
|
"updateCampus":"编辑校区", |
||||
|
"campusDeleteTips":"确定要删除该数据吗?", |
||||
|
"startDate":"请选择开始时间", |
||||
|
"endDate":"请选择结束时间" |
||||
|
} |
||||
@ -0,0 +1,203 @@ |
|||||
|
<template> |
||||
|
<div class="main-container"> |
||||
|
<el-card class="box-card !border-none" shadow="never"> |
||||
|
|
||||
|
<div class="flex justify-between items-center"> |
||||
|
<span class="text-lg">{{pageName}}</span> |
||||
|
<el-button type="primary" @click="addEvent"> |
||||
|
{{ t('addCampus') }} |
||||
|
</el-button> |
||||
|
</div> |
||||
|
|
||||
|
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never"> |
||||
|
<el-form :inline="true" :model="campusTable.searchParam" ref="searchFormRef"> |
||||
|
<el-form-item :label="t('campusName')" prop="campus_name"> |
||||
|
<el-input v-model="campusTable.searchParam.campus_name" :placeholder="t('campusNamePlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('campusAddress')" prop="campus_address"> |
||||
|
<el-input v-model="campusTable.searchParam.campus_address" :placeholder="t('campusAddressPlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('campusPreviewImage')" prop="campus_preview_image"> |
||||
|
<el-input v-model="campusTable.searchParam.campus_preview_image" :placeholder="t('campusPreviewImagePlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('campusCoordinates')" prop="campus_coordinates"> |
||||
|
<el-input v-model="campusTable.searchParam.campus_coordinates" :placeholder="t('campusCoordinatesPlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('campusIntroduction')" prop="campus_introduction"> |
||||
|
<el-input v-model="campusTable.searchParam.campus_introduction" :placeholder="t('campusIntroductionPlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('campusStatus')" prop="campus_status"> |
||||
|
<el-input v-model="campusTable.searchParam.campus_status" :placeholder="t('campusStatusPlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('createTime')" prop="create_time"> |
||||
|
<el-input v-model="campusTable.searchParam.create_time" :placeholder="t('createTimePlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('updateTime')" prop="update_time"> |
||||
|
<el-input v-model="campusTable.searchParam.update_time" :placeholder="t('updateTimePlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item :label="t('deleteTime')" prop="delete_time"> |
||||
|
<el-input v-model="campusTable.searchParam.delete_time" :placeholder="t('deleteTimePlaceholder')" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" @click="loadCampusList()">{{ t('search') }}</el-button> |
||||
|
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</el-card> |
||||
|
|
||||
|
<div class="mt-[10px]"> |
||||
|
<el-table :data="campusTable.data" size="large" v-loading="campusTable.loading"> |
||||
|
<template #empty> |
||||
|
<span>{{ !campusTable.loading ? t('emptyData') : '' }}</span> |
||||
|
</template> |
||||
|
<el-table-column prop="campus_name" :label="t('campusName')" min-width="120" :show-overflow-tooltip="true"/> |
||||
|
|
||||
|
<el-table-column prop="campus_address" :label="t('campusAddress')" min-width="120" :show-overflow-tooltip="true"/> |
||||
|
|
||||
|
<el-table-column prop="campus_preview_image" :label="t('campusPreviewImage')" min-width="120" :show-overflow-tooltip="true"/> |
||||
|
|
||||
|
<el-table-column prop="campus_coordinates" :label="t('campusCoordinates')" min-width="120" :show-overflow-tooltip="true"/> |
||||
|
|
||||
|
<el-table-column prop="campus_introduction" :label="t('campusIntroduction')" min-width="120" :show-overflow-tooltip="true"/> |
||||
|
|
||||
|
<el-table-column prop="campus_status" :label="t('campusStatus')" min-width="120" :show-overflow-tooltip="true"/> |
||||
|
|
||||
|
<el-table-column prop="delete_time" :label="t('deleteTime')" min-width="120" :show-overflow-tooltip="true"/> |
||||
|
|
||||
|
<el-table-column :label="t('operation')" fixed="right" min-width="120"> |
||||
|
<template #default="{ row }"> |
||||
|
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button> |
||||
|
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
|
||||
|
</el-table> |
||||
|
<div class="mt-[16px] flex justify-end"> |
||||
|
<el-pagination v-model:current-page="campusTable.page" v-model:page-size="campusTable.limit" |
||||
|
layout="total, sizes, prev, pager, next, jumper" :total="campusTable.total" |
||||
|
@size-change="loadCampusList()" @current-change="loadCampusList" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<edit ref="editCampusDialog" @complete="loadCampusList" /> |
||||
|
</el-card> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { reactive, ref, watch } from 'vue' |
||||
|
import { t } from '@/lang' |
||||
|
import { useDictionary } from '@/app/api/dict' |
||||
|
import { getCampusList, deleteCampus } from '@/app/api/campus' |
||||
|
import { img } from '@/utils/common' |
||||
|
import { ElMessageBox,FormInstance } from 'element-plus' |
||||
|
import Edit from '@/app/views/campus/components/campus-edit.vue' |
||||
|
import { useRoute } from 'vue-router' |
||||
|
const route = useRoute() |
||||
|
const pageName = route.meta.title; |
||||
|
|
||||
|
let campusTable = reactive({ |
||||
|
page: 1, |
||||
|
limit: 10, |
||||
|
total: 0, |
||||
|
loading: true, |
||||
|
data: [], |
||||
|
searchParam:{ |
||||
|
"campus_name":"", |
||||
|
"campus_address":"", |
||||
|
"campus_preview_image":"", |
||||
|
"campus_coordinates":"", |
||||
|
"campus_introduction":"", |
||||
|
"campus_status":"", |
||||
|
"create_time":"", |
||||
|
"update_time":"", |
||||
|
"delete_time":"" |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
const searchFormRef = ref<FormInstance>() |
||||
|
|
||||
|
// 选中数据 |
||||
|
const selectData = ref<any[]>([]) |
||||
|
|
||||
|
// 字典数据 |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 获取校区列表 |
||||
|
*/ |
||||
|
const loadCampusList = (page: number = 1) => { |
||||
|
campusTable.loading = true |
||||
|
campusTable.page = page |
||||
|
|
||||
|
getCampusList({ |
||||
|
page: campusTable.page, |
||||
|
limit: campusTable.limit, |
||||
|
...campusTable.searchParam |
||||
|
}).then(res => { |
||||
|
campusTable.loading = false |
||||
|
campusTable.data = res.data.data |
||||
|
campusTable.total = res.data.total |
||||
|
}).catch(() => { |
||||
|
campusTable.loading = false |
||||
|
}) |
||||
|
} |
||||
|
loadCampusList() |
||||
|
|
||||
|
const editCampusDialog: Record<string, any> | null = ref(null) |
||||
|
|
||||
|
/** |
||||
|
* 添加校区 |
||||
|
*/ |
||||
|
const addEvent = () => { |
||||
|
editCampusDialog.value.setFormData() |
||||
|
editCampusDialog.value.showDialog = true |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 编辑校区 |
||||
|
* @param data |
||||
|
*/ |
||||
|
const editEvent = (data: any) => { |
||||
|
editCampusDialog.value.setFormData(data) |
||||
|
editCampusDialog.value.showDialog = true |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除校区 |
||||
|
*/ |
||||
|
const deleteEvent = (id: number) => { |
||||
|
ElMessageBox.confirm(t('campusDeleteTips'), t('warning'), |
||||
|
{ |
||||
|
confirmButtonText: t('confirm'), |
||||
|
cancelButtonText: t('cancel'), |
||||
|
type: 'warning', |
||||
|
} |
||||
|
).then(() => { |
||||
|
deleteCampus(id).then(() => { |
||||
|
loadCampusList() |
||||
|
}).catch(() => { |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
const resetForm = (formEl: FormInstance | undefined) => { |
||||
|
if (!formEl) return |
||||
|
formEl.resetFields() |
||||
|
loadCampusList() |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
/* 多行超出隐藏 */ |
||||
|
.multi-hidden { |
||||
|
word-break: break-all; |
||||
|
text-overflow: ellipsis; |
||||
|
overflow: hidden; |
||||
|
display: -webkit-box; |
||||
|
-webkit-line-clamp: 2; |
||||
|
-webkit-box-orient: vertical; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,203 @@ |
|||||
|
<template> |
||||
|
<el-dialog v-model="showDialog" :title="formData.id ? t('updateCampus') : t('addCampus')" width="50%" class="diy-dialog-wrap" :destroy-on-close="true"> |
||||
|
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading"> |
||||
|
<el-form-item :label="t('campusName')" prop="campus_name"> |
||||
|
<el-input v-model="formData.campus_name" clearable :placeholder="t('campusNamePlaceholder')" class="input-width" /> |
||||
|
</el-form-item> |
||||
|
|
||||
|
<el-form-item :label="t('campusAddress')" prop="campus_address"> |
||||
|
<el-input v-model="formData.campus_address" clearable :placeholder="t('campusAddressPlaceholder')" class="input-width" /> |
||||
|
</el-form-item> |
||||
|
|
||||
|
<el-form-item :label="t('campusPreviewImage')" > |
||||
|
<el-input v-model="formData.campus_preview_image" clearable :placeholder="t('campusPreviewImagePlaceholder')" class="input-width" /> |
||||
|
</el-form-item> |
||||
|
|
||||
|
<el-form-item :label="t('campusCoordinates')" > |
||||
|
<el-input v-model="formData.campus_coordinates" clearable :placeholder="t('campusCoordinatesPlaceholder')" class="input-width" /> |
||||
|
</el-form-item> |
||||
|
|
||||
|
<el-form-item :label="t('campusIntroduction')" > |
||||
|
<el-input v-model="formData.campus_introduction" clearable :placeholder="t('campusIntroductionPlaceholder')" class="input-width" /> |
||||
|
</el-form-item> |
||||
|
|
||||
|
<el-form-item :label="t('campusStatus')" > |
||||
|
<el-input v-model="formData.campus_status" clearable :placeholder="t('campusStatusPlaceholder')" class="input-width" /> |
||||
|
</el-form-item> |
||||
|
|
||||
|
<el-form-item :label="t('deleteTime')" > |
||||
|
<el-input v-model="formData.delete_time" clearable :placeholder="t('deleteTimePlaceholder')" class="input-width" /> |
||||
|
</el-form-item> |
||||
|
|
||||
|
</el-form> |
||||
|
|
||||
|
<template #footer> |
||||
|
<span class="dialog-footer"> |
||||
|
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button> |
||||
|
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ |
||||
|
t('confirm') |
||||
|
}}</el-button> |
||||
|
</span> |
||||
|
</template> |
||||
|
</el-dialog> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { ref, reactive, computed, watch } from 'vue' |
||||
|
import { useDictionary } from '@/app/api/dict' |
||||
|
import { t } from '@/lang' |
||||
|
import type { FormInstance } from 'element-plus' |
||||
|
import { addCampus, editCampus, getCampusInfo } from '@/app/api/campus' |
||||
|
|
||||
|
let showDialog = ref(false) |
||||
|
const loading = ref(false) |
||||
|
|
||||
|
/** |
||||
|
* 表单数据 |
||||
|
*/ |
||||
|
const initialFormData = { |
||||
|
id: '', |
||||
|
campus_name: '', |
||||
|
campus_address: '', |
||||
|
campus_preview_image: '', |
||||
|
campus_coordinates: '', |
||||
|
campus_introduction: '', |
||||
|
campus_status: '', |
||||
|
delete_time: '', |
||||
|
} |
||||
|
const formData: Record<string, any> = reactive({ ...initialFormData }) |
||||
|
|
||||
|
const formRef = ref<FormInstance>() |
||||
|
|
||||
|
// 表单验证规则 |
||||
|
const formRules = computed(() => { |
||||
|
return { |
||||
|
campus_name: [ |
||||
|
{ required: true, message: t('campusNamePlaceholder'), trigger: 'blur' }, |
||||
|
|
||||
|
] |
||||
|
, |
||||
|
campus_address: [ |
||||
|
{ required: true, message: t('campusAddressPlaceholder'), trigger: 'blur' }, |
||||
|
|
||||
|
] |
||||
|
, |
||||
|
campus_preview_image: [ |
||||
|
{ required: true, message: t('campusPreviewImagePlaceholder'), trigger: 'blur' }, |
||||
|
|
||||
|
] |
||||
|
, |
||||
|
campus_coordinates: [ |
||||
|
{ required: true, message: t('campusCoordinatesPlaceholder'), trigger: 'blur' }, |
||||
|
|
||||
|
] |
||||
|
, |
||||
|
campus_introduction: [ |
||||
|
{ required: true, message: t('campusIntroductionPlaceholder'), trigger: 'blur' }, |
||||
|
|
||||
|
] |
||||
|
, |
||||
|
campus_status: [ |
||||
|
{ required: true, message: t('campusStatusPlaceholder'), trigger: 'blur' }, |
||||
|
|
||||
|
] |
||||
|
, |
||||
|
delete_time: [ |
||||
|
{ required: true, message: t('deleteTimePlaceholder'), trigger: 'blur' }, |
||||
|
|
||||
|
] |
||||
|
, |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
const emit = defineEmits(['complete']) |
||||
|
|
||||
|
/** |
||||
|
* 确认 |
||||
|
* @param formEl |
||||
|
*/ |
||||
|
const confirm = async (formEl: FormInstance | undefined) => { |
||||
|
if (loading.value || !formEl) return |
||||
|
let save = formData.id ? editCampus : addCampus |
||||
|
|
||||
|
await formEl.validate(async (valid) => { |
||||
|
if (valid) { |
||||
|
loading.value = true |
||||
|
|
||||
|
let data = formData |
||||
|
|
||||
|
save(data).then(res => { |
||||
|
loading.value = false |
||||
|
showDialog.value = false |
||||
|
emit('complete') |
||||
|
}).catch(err => { |
||||
|
loading.value = false |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 获取字典数据 |
||||
|
|
||||
|
|
||||
|
|
||||
|
const setFormData = async (row: any = null) => { |
||||
|
Object.assign(formData, initialFormData) |
||||
|
loading.value = true |
||||
|
if(row){ |
||||
|
const data = await (await getCampusInfo(row.id)).data |
||||
|
if (data) Object.keys(formData).forEach((key: string) => { |
||||
|
if (data[key] != undefined) formData[key] = data[key] |
||||
|
}) |
||||
|
} |
||||
|
loading.value = false |
||||
|
} |
||||
|
|
||||
|
// 验证手机号格式 |
||||
|
const mobileVerify = (rule: any, value: any, callback: any) => { |
||||
|
if (value && !/^1[3-9]\d{9}$/.test(value)) { |
||||
|
callback(new Error(t('generateMobile'))) |
||||
|
} else { |
||||
|
callback() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 验证身份证号 |
||||
|
const idCardVerify = (rule: any, value: any, callback: any) => { |
||||
|
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) { |
||||
|
callback(new Error(t('generateIdCard'))) |
||||
|
} else { |
||||
|
callback() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 验证邮箱号 |
||||
|
const emailVerify = (rule: any, value: any, callback: any) => { |
||||
|
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) { |
||||
|
callback(new Error(t('generateEmail'))) |
||||
|
} else { |
||||
|
callback() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 验证请输入整数 |
||||
|
const numberVerify = (rule: any, value: any, callback: any) => { |
||||
|
if (!Number.isInteger(value)) { |
||||
|
callback(new Error(t('generateNumber'))) |
||||
|
} else { |
||||
|
callback() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
defineExpose({ |
||||
|
showDialog, |
||||
|
setFormData |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped></style> |
||||
|
<style lang="scss"> |
||||
|
.diy-dialog-wrap .el-form-item__label{ |
||||
|
height: auto !important; |
||||
|
} |
||||
|
</style> |
||||
@ -1 +0,0 @@ |
|||||
APP_DEBUG = true
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
AUTH_KEY = gogheyxfainjsraqdbusphmvcfdtkwzl
PRODUCT_KEY = {product_key}
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = new_school_oa
USERNAME = new_school_oa
PASSWORD = f8a27896b1
HOSTPORT = 3306
PREFIX = school_
CHARSET = utf8mb4
DEBUG = false
[REDIS]
REDIS_HOSTNAME = 127.0.0.1
PORT = 6379
REDIS_PASSWORD =
SELECT = 0
[QUEUE]
state = false
[LANG]
default_lang = zh-cn
[SYSTEM]
ADMIN_TOKEN_NAME = token
API_TOKEN_NAME = token
ADMIN_TOKEN_EXPIRE_TIME = 604800
API_TOKEN_EXPIRE_TIME = 86400
LANG_NAME = lang
CHANNEL_NAME = channel
ADMIN_DOMAIN =
WAP_DOMAIN =
WEB_DOMAIN =
[NIUCLOUD]
code =
secret = |
|
||||
@ -0,0 +1,103 @@ |
|||||
|
<?php |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Niucloud-admin 企业快速开发的多应用管理平台 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | 官方网址:https://www.niucloud.com |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | niucloud团队 版权所有 开源版本可自由商用 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Author: Niucloud Team |
||||
|
// +---------------------------------------------------------------------- |
||||
|
|
||||
|
namespace app\adminapi\controller\campus; |
||||
|
|
||||
|
use core\base\BaseAdminController; |
||||
|
use app\service\admin\campus\CampusService; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 校区控制器 |
||||
|
* Class Campus |
||||
|
* @package app\adminapi\controller\campus |
||||
|
*/ |
||||
|
class Campus extends BaseAdminController |
||||
|
{ |
||||
|
/** |
||||
|
* 获取校区列表 |
||||
|
* @return \think\Response |
||||
|
*/ |
||||
|
public function lists(){ |
||||
|
$data = $this->request->params([ |
||||
|
["campus_name",""], |
||||
|
["campus_address",""], |
||||
|
["campus_preview_image",""], |
||||
|
["campus_coordinates",""], |
||||
|
["campus_introduction",""], |
||||
|
["campus_status",""], |
||||
|
["create_time",""], |
||||
|
["update_time",""], |
||||
|
["delete_time",""] |
||||
|
]); |
||||
|
return success((new CampusService())->getPage($data)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 校区详情 |
||||
|
* @param int $id |
||||
|
* @return \think\Response |
||||
|
*/ |
||||
|
public function info(int $id){ |
||||
|
return success((new CampusService())->getInfo($id)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加校区 |
||||
|
* @return \think\Response |
||||
|
*/ |
||||
|
public function add(){ |
||||
|
$data = $this->request->params([ |
||||
|
["campus_name",""], |
||||
|
["campus_address",""], |
||||
|
["campus_preview_image",""], |
||||
|
["campus_coordinates",""], |
||||
|
["campus_introduction",""], |
||||
|
["campus_status",0], |
||||
|
["delete_time",1747295250] |
||||
|
]); |
||||
|
$this->validate($data, 'app\validate\campus\Campus.add'); |
||||
|
$id = (new CampusService())->add($data); |
||||
|
return success('ADD_SUCCESS', ['id' => $id]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 校区编辑 |
||||
|
* @param $id 校区id |
||||
|
* @return \think\Response |
||||
|
*/ |
||||
|
public function edit(int $id){ |
||||
|
$data = $this->request->params([ |
||||
|
["campus_name",""], |
||||
|
["campus_address",""], |
||||
|
["campus_preview_image",""], |
||||
|
["campus_coordinates",""], |
||||
|
["campus_introduction",""], |
||||
|
["campus_status",0], |
||||
|
["delete_time",1747295250] |
||||
|
]); |
||||
|
$this->validate($data, 'app\validate\campus\Campus.edit'); |
||||
|
(new CampusService())->edit($id, $data); |
||||
|
return success('EDIT_SUCCESS'); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 校区删除 |
||||
|
* @param $id 校区id |
||||
|
* @return \think\Response |
||||
|
*/ |
||||
|
public function del(int $id){ |
||||
|
(new CampusService())->del($id); |
||||
|
return success('DELETE_SUCCESS'); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
<?php |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Niucloud-admin 企业快速开发的多应用管理平台 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | 官方网址:https://www.niucloud.com |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | niucloud团队 版权所有 开源版本可自由商用 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Author: Niucloud Team |
||||
|
// +---------------------------------------------------------------------- |
||||
|
|
||||
|
use think\facade\Route; |
||||
|
|
||||
|
use app\adminapi\middleware\AdminCheckRole; |
||||
|
use app\adminapi\middleware\AdminCheckToken; |
||||
|
use app\adminapi\middleware\AdminLog; |
||||
|
// USER_CODE_BEGIN -- campus |
||||
|
|
||||
|
Route::group('campus', function () { |
||||
|
|
||||
|
//校区列表 |
||||
|
Route::get('campus', 'campus.Campus/lists'); |
||||
|
//校区详情 |
||||
|
Route::get('campus/:id', 'campus.Campus/info'); |
||||
|
//添加校区 |
||||
|
Route::post('campus', 'campus.Campus/add'); |
||||
|
//编辑校区 |
||||
|
Route::put('campus/:id', 'campus.Campus/edit'); |
||||
|
//删除校区 |
||||
|
Route::delete('campus/:id', 'campus.Campus/del'); |
||||
|
|
||||
|
})->middleware([ |
||||
|
AdminCheckToken::class, |
||||
|
AdminCheckRole::class, |
||||
|
AdminLog::class |
||||
|
]); |
||||
|
// USER_CODE_END -- campus |
||||
@ -0,0 +1,170 @@ |
|||||
|
<?php |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Niucloud-admin 企业快速开发的多应用管理平台 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | 官方网址:https://www.niucloud.com |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | niucloud团队 版权所有 开源版本可自由商用 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Author: Niucloud Team |
||||
|
// +---------------------------------------------------------------------- |
||||
|
|
||||
|
namespace app\model\campus; |
||||
|
|
||||
|
use core\base\BaseModel; |
||||
|
use think\model\concern\SoftDelete; |
||||
|
use think\model\relation\HasMany; |
||||
|
use think\model\relation\HasOne; |
||||
|
|
||||
|
/** |
||||
|
* 校区模型 |
||||
|
* Class Campus |
||||
|
* @package app\model\campus |
||||
|
*/ |
||||
|
class Campus extends BaseModel |
||||
|
{ |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 数据表主键 |
||||
|
* @var string |
||||
|
*/ |
||||
|
protected $pk = 'id'; |
||||
|
|
||||
|
/** |
||||
|
* 模型名称 |
||||
|
* @var string |
||||
|
*/ |
||||
|
protected $name = 'campus'; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区主键ID |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchIdAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("id", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区名称 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchCampusNameAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("campus_name", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区地址 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchCampusAddressAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("campus_address", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区预览图,存储图片路径 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchCampusPreviewImageAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("campus_preview_image", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区坐标,格式为经度,纬度 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchCampusCoordinatesAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("campus_coordinates", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区介绍 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchCampusIntroductionAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("campus_introduction", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区状态:0-禁用,1-启用 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchCampusStatusAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("campus_status", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区创建时间 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchCreateTimeAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("create_time", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区校区更新时间 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchUpdateTimeAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("update_time", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 搜索器:校区逻辑删除字段,NULL表示未删除,非空表示已删除 |
||||
|
* @param $value |
||||
|
* @param $data |
||||
|
*/ |
||||
|
public function searchDeleteTimeAttr($query, $value, $data) |
||||
|
{ |
||||
|
if ($value) { |
||||
|
$query->where("delete_time", $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,99 @@ |
|||||
|
<?php |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Niucloud-admin 企业快速开发的多应用管理平台 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | 官方网址:https://www.niucloud.com |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | niucloud团队 版权所有 开源版本可自由商用 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Author: Niucloud Team |
||||
|
// +---------------------------------------------------------------------- |
||||
|
|
||||
|
namespace app\service\admin\campus; |
||||
|
|
||||
|
use app\model\campus\Campus; |
||||
|
|
||||
|
use core\base\BaseAdminService; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 校区服务层 |
||||
|
* Class CampusService |
||||
|
* @package app\service\admin\campus |
||||
|
*/ |
||||
|
class CampusService extends BaseAdminService |
||||
|
{ |
||||
|
public function __construct() |
||||
|
{ |
||||
|
parent::__construct(); |
||||
|
$this->model = new Campus(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取校区列表 |
||||
|
* @param array $where |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getPage(array $where = []) |
||||
|
{ |
||||
|
$field = 'id,campus_name,campus_address,campus_preview_image,campus_coordinates,campus_introduction,campus_status,create_time,update_time,delete_time'; |
||||
|
$order = ''; |
||||
|
|
||||
|
$search_model = $this->model->withSearch(["id","campus_name","campus_address","campus_preview_image","campus_coordinates","campus_introduction","campus_status","create_time","update_time","delete_time"], $where)->field($field)->order($order); |
||||
|
$list = $this->pageQuery($search_model); |
||||
|
return $list; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取校区信息 |
||||
|
* @param int $id |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getInfo(int $id) |
||||
|
{ |
||||
|
$field = 'id,campus_name,campus_address,campus_preview_image,campus_coordinates,campus_introduction,campus_status,create_time,update_time,delete_time'; |
||||
|
|
||||
|
$info = $this->model->field($field)->where([['id', "=", $id]])->findOrEmpty()->toArray(); |
||||
|
return $info; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加校区 |
||||
|
* @param array $data |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function add(array $data) |
||||
|
{ |
||||
|
$res = $this->model->create($data); |
||||
|
return $res->id; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 校区编辑 |
||||
|
* @param int $id |
||||
|
* @param array $data |
||||
|
* @return bool |
||||
|
*/ |
||||
|
public function edit(int $id, array $data) |
||||
|
{ |
||||
|
|
||||
|
$this->model->where([['id', '=', $id]])->update($data); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除校区 |
||||
|
* @param int $id |
||||
|
* @return bool |
||||
|
*/ |
||||
|
public function del(int $id) |
||||
|
{ |
||||
|
$model = $this->model->where([['id', '=', $id]])->find(); |
||||
|
$res = $model->delete(); |
||||
|
return $res; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
<?php |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Niucloud-admin 企业快速开发的多应用管理平台 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | 官方网址:https://www.niucloud.com |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | niucloud团队 版权所有 开源版本可自由商用 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Author: Niucloud Team |
||||
|
// +---------------------------------------------------------------------- |
||||
|
|
||||
|
namespace app\validate\campus; |
||||
|
use core\base\BaseValidate; |
||||
|
/** |
||||
|
* 校区验证器 |
||||
|
* Class Campus |
||||
|
* @package addon\app\validate\campus |
||||
|
*/ |
||||
|
class Campus extends BaseValidate |
||||
|
{ |
||||
|
|
||||
|
protected $rule = [ |
||||
|
'campus_name' => 'require', |
||||
|
'campus_address' => 'require', |
||||
|
]; |
||||
|
|
||||
|
protected $message = [ |
||||
|
'campus_name.require' => ['common_validate.require', ['campus_name']], |
||||
|
'campus_address.require' => ['common_validate.require', ['campus_address']], |
||||
|
]; |
||||
|
|
||||
|
protected $scene = [ |
||||
|
"add" => ['campus_name', 'campus_address', 'campus_preview_image', 'campus_coordinates', 'campus_introduction', 'campus_status', 'delete_time'], |
||||
|
"edit" => ['campus_name', 'campus_address', 'campus_preview_image', 'campus_coordinates', 'campus_introduction', 'campus_status', 'delete_time'] |
||||
|
]; |
||||
|
|
||||
|
} |
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"8tc4bcd3aq4tm5mz";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:212;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:1:{i:0;s:4:"shop";} |
|
||||
File diff suppressed because one or more lines are too long
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"t1y1fkfbpiwp90z2";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:220;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:4:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/8d/4b55ce338f9b3a100a33ac8e8243e8.php";i:1;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/20/336a007c8134208722cf4e14270f07.php";i:2;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/32/0a87fb2f5a7e9725055a2c99bd1e51.php";i:3;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/5a/b59a6b9098844b87383115074eeae6.php";} |
|
||||
File diff suppressed because one or more lines are too long
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:1:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/85/dff97d885b41077c47958d953c2dbd.php";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:1:{i:0;a:6:{s:5:"title";s:12:"商城系统";s:4:"icon";s:19:"addon/shop/icon.png";s:3:"key";s:4:"shop";s:4:"desc";s:63:"实物虚拟商品,订单,物流同城配送,门店自提";s:6:"status";i:1;s:5:"cover";s:20:"addon/shop/cover.png";}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"buxxhve44knbv39r";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:182;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"a9o0ru62yhy3ipvi";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:259;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"7blh529w0qefmdt9";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:245;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:6:{s:2:"id";i:1;s:10:"config_key";s:15:"NIUCLOUD_CONFIG";s:5:"value";a:2:{s:9:"auth_code";s:23:"20250514564159522820096";s:11:"auth_secret";s:13:"68240e727a56a";}s:6:"status";i:1;s:11:"create_time";s:19:"2025-05-14 11:36:38";s:11:"update_time";s:19:"2025-05-14 11:36:38";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"570l4om645vy3ir5";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:218;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"uqswflt3b4v2d6fz";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:257;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"na3bmmvql6hfn5mu";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:260;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:0:{} |
|
||||
File diff suppressed because one or more lines are too long
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:11:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/47/0f6e29f334d3244ee0749eb9b1a151.php";i:1;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/01/c8e2ef1c2c504601d752e81c5f8f57.php";i:2;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/04/a77b15025b2c34a79ecfe786681739.php";i:3;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/f4/2498c1c8e75342476a682f6f5bbba6.php";i:4;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/95/228e6be1c6483f594d6d736cba9335.php";i:5;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/f4/073ed8013d62bb2e0f768418925e4d.php";i:6;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/c0/2ea470914e2a1b4422c74fb53b3fb7.php";i:7;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/c8/a5c3cd9f43d503a892ec0eaeb9ab08.php";i:8;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/8d/edc20f770c6500c52ce13d6f306b10.php";i:9;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/f0/8f735f0ec7f9eccc3e70aa516d941d.php";i:10;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/63/223550b09d74c7a7f49224de60bf39.php";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"7adolb3be3dfg93m";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:244;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"q70goxi4h1ok01fp";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:195;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"q3gp3ysh8uayxtoo";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:263;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:2:{s:8:"username";s:5:"admin";s:8:"password";s:6:"123123";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:1:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/11/96761b4a84f0e988872166216d02cd.php";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:0:{} |
|
||||
File diff suppressed because one or more lines are too long
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:6:{i:0;s:264:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJpc3MiOiJ6aC5obmhidHkuY24iLCJhdWQiOiJ6aC5obmhidHkuY24iLCJpYXQiOjE3NDcxOTM0MTcsIm5iZiI6MTc0NzE5MzQxNywiZXhwIjoxNzQ3Nzk4MjE3LCJqdGkiOiIxX2FkbWluIn0.3Jv4XN3QLngUh6gOMlk9NJqX5XSjQ-Ys-SeAVTEm9fA";i:1;s:264:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJpc3MiOiJ6aC5obmhidHkuY24iLCJhdWQiOiJ6aC5obmhidHkuY24iLCJpYXQiOjE3NDcxOTM0MzcsIm5iZiI6MTc0NzE5MzQzNywiZXhwIjoxNzQ3Nzk4MjM3LCJqdGkiOiIxX2FkbWluIn0.nWDtG3Ckln2oVF14IFn_8dCWsOWRwkhRZRzzecpOtXk";i:2;s:264:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJpc3MiOiJ6aC5obmhidHkuY24iLCJhdWQiOiJ6aC5obmhidHkuY24iLCJpYXQiOjE3NDcxOTM1OTcsIm5iZiI6MTc0NzE5MzU5NywiZXhwIjoxNzQ3Nzk4Mzk3LCJqdGkiOiIxX2FkbWluIn0.KVNyHg7sNFhdAIdTXDvOM133kzfJqPATdQ5N42DLw7k";i:3;s:264:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJpc3MiOiJ6aC5obmhidHkuY24iLCJhdWQiOiJ6aC5obmhidHkuY24iLCJpYXQiOjE3NDcxOTM3ODksIm5iZiI6MTc0NzE5Mzc4OSwiZXhwIjoxNzQ3Nzk4NTg5LCJqdGkiOiIxX2FkbWluIn0.Kw1Ovhz6Ck4sfkvGDbY8BGPJu_VjbDpY0q5q8WFvGIo";i:4;s:264:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJpc3MiOiJ6aC5obmhidHkuY24iLCJhdWQiOiJ6aC5obmhidHkuY24iLCJpYXQiOjE3NDcxOTUwMTIsIm5iZiI6MTc0NzE5NTAxMiwiZXhwIjoxNzQ3Nzk5ODEyLCJqdGkiOiIxX2FkbWluIn0.16YcP5javxVsQqkF9qZrSExZiXrkHzQ5QaUWRTE3p-o";i:5;s:264:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJpc3MiOiJ6aC5obmhidHkuY24iLCJhdWQiOiJ6aC5obmhidHkuY24iLCJpYXQiOjE3NDcxOTY3MTcsIm5iZiI6MTc0NzE5NjcxNywiZXhwIjoxNzQ3ODAxNTE3LCJqdGkiOiIxX2FkbWluIn0.nNIIFD2ZMXC5kzo5-Jhnj5ZQCO5WT0LDNTtIjhb8T74";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:2:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/3d/23e92f6d905dabf364fea237dcc9b2.php";i:1;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/58/745cacd434435731821012c2ecfd90.php";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:1:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/8d/fdacbfbb7ae58ba988054e909e2307.php";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:1:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/a2/c8f1f64a1c2171c95fce93be9d7fad.php";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:14:{s:11:"status_name";s:6:"正常";s:3:"uid";i:1;s:8:"username";s:5:"admin";s:8:"head_img";s:0:"";s:9:"real_name";s:0:"";s:7:"last_ip";s:15:"182.200.111.164";s:9:"last_time";s:19:"2025-05-14 11:30:37";s:11:"create_time";s:0:"";s:11:"login_count";i:2;s:6:"status";i:1;s:11:"delete_time";i:0;s:11:"update_time";s:19:"2025-05-14 11:30:37";s:8:"role_ids";N;s:8:"is_admin";i:1;} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"rwh4tvfn2guladm7";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:199;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
N; |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"34azy4s5kckw2stg";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:262;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"80ani9vtgil9buf2";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:174;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"8lznwh6t1nm4ts19";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:216;s:1:"y";i:5;}} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
a:1:{i:0;s:83:"/www/wwwroot/hnhbty.cn/niucloud/runtime/cache/a2/c8f1f64a1c2171c95fce93be9d7fad.php";} |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000000 |
|
||||
exit();?> |
|
||||
-1 |
|
||||
@ -1,4 +0,0 @@ |
|||||
<?php |
|
||||
//000000000300 |
|
||||
exit();?> |
|
||||
a:2:{s:9:"secretKey";s:16:"13ywro0h0s94nttx";s:5:"point";O:27:"Fastknife\Domain\Vo\PointVo":2:{s:1:"x";i:244;s:1:"y";i:5;}} |
|
||||
@ -1,291 +0,0 @@ |
|||||
<?php /*a:2:{s:66:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/index/step-5.html";i:1740994438;s:58:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/base.html";i:1740994438;}*/ ?> |
|
||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
<head> |
|
||||
<meta name="renderer" content="webkit" /> |
|
||||
<meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1" /> |
|
||||
<title>安装程序 - <?php echo htmlentities($install_config['website_name']); ?></title> |
|
||||
<link rel="icon" type="image/x-icon" href="/install/img/shop_bitbug_favicon.ico" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/style.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/layui.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/common.css" /> |
|
||||
<script src="/install/js/jquery-3.1.1.js"></script> |
|
||||
<script src="/install/js/layui.js"></script> |
|
||||
|
|
||||
<script> |
|
||||
layui.use(['layer', 'upload', 'element'], function() {}); |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
.install-content-procedure .content-procedure-item:first-of-type{ |
|
||||
background: url("/install/img/complete_two.png") no-repeat center / contain; |
|
||||
color: #fff; |
|
||||
} |
|
||||
.install-content-procedure .content-procedure-item:nth-child(2), .install-content-procedure .content-procedure-item:nth-child(3){ |
|
||||
background: url("/install/img/complete_four.png") no-repeat center / contain; |
|
||||
color: #fff; |
|
||||
} |
|
||||
.install-content-procedure .content-procedure-item:nth-child(4){ |
|
||||
background: url("/install/img/complete_three.png") no-repeat center / contain; |
|
||||
color: #fff; |
|
||||
} |
|
||||
.install-content-procedure{border: none;} |
|
||||
.pop-link-wrap{ |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
} |
|
||||
.pop-link-wrap .link-text{ |
|
||||
font-size: 14px; |
|
||||
} |
|
||||
.pop-link-wrap .link-text:nth-child(2){ |
|
||||
margin-top: 10px; |
|
||||
} |
|
||||
.pop-link-wrap .link-text:nth-child(2) a{ |
|
||||
color: var(--base-color); |
|
||||
} |
|
||||
.pop-link-wrap .link-btn{ |
|
||||
margin-top: 40px; |
|
||||
} |
|
||||
|
|
||||
.pop-link-wrap button{ |
|
||||
width: 160px; |
|
||||
height: 40px; |
|
||||
background: var(--base-color); |
|
||||
color: #fff !important; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
</head> |
|
||||
|
|
||||
<body> |
|
||||
<div class="head-block"> |
|
||||
<div class="top"> |
|
||||
<div class="top-logo"> |
|
||||
<div class="top-logo-img"> |
|
||||
<?php if(is_url($install_config['logo'])): ?> |
|
||||
<img src="<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php else: ?> |
|
||||
<img src="/install/img/<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php endif; ?> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="top-sub" style="flex:1;"></div> |
|
||||
<ul class="top-link"> |
|
||||
<?php if(!(empty($install_config['website_url']) || (($install_config['website_url'] instanceof \think\Collection || $install_config['website_url'] instanceof \think\Paginator ) && $install_config['website_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['website_url']); ?>" target="_blank">官方网站</a></li><?php endif; if(!(empty($install_config['bbs_url']) || (($install_config['bbs_url'] instanceof \think\Collection || $install_config['bbs_url'] instanceof \think\Paginator ) && $install_config['bbs_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['bbs_url']); ?>" target="_blank">技术论坛</a></li><?php endif; ?> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="step-content"> |
|
||||
<div style="width:1000px;margin:0 auto;"> |
|
||||
|
|
||||
<!-- 标题进度条 start--> |
|
||||
<div class="content" style="margin:30px 0 0 0;width: 100%;"> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -53px;"><span class='poetry'>1.许可协议</span></div> |
|
||||
<div id="line0" class="bar"> |
|
||||
<div id="point0" class="c-step c-select"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>2.环境检测</span></div> |
|
||||
<div id="line1" class="bar"> |
|
||||
<div id="point1" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>3.参数配置</span></div> |
|
||||
<div id="line2" class="bar"> |
|
||||
<div id="point2" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -50px;"><span class='poetry'>4.代码编译</span></div> |
|
||||
<div id="line3" class="bar"> |
|
||||
<div id="point3" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar" style="width:10px;"> |
|
||||
<div class="text" style="margin: 10px -39px;"><span class='poetry'>5.安装完成</span></div> |
|
||||
<div id="line4" class="bar" style="width: 0;"> |
|
||||
<div id="point4" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- 标题进度条 end--> |
|
||||
<div style="clear: both;"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="install-content"> |
|
||||
|
|
||||
<div class="install-success"> |
|
||||
<div class="install-success-box"> |
|
||||
<div class="success-img"> |
|
||||
<img class="install-success-pic" src="/install/img/success_img.png" alt=""> |
|
||||
</div> |
|
||||
<div class="install-success-text"> |
|
||||
<?php if($is_build == 1): ?> |
|
||||
<p class="install-success-title">恭喜您!已成功安装<?php echo htmlentities($install_config['website_name']); ?>。</p> |
|
||||
<?php endif; if($is_build == 0): ?> |
|
||||
<p class="install-success-title">安装过程已结束,您还需要手动编译,才能正常使用! </p> |
|
||||
<p class="install-success-desc">如何手动编译请参考如下链接 <a href="<?php echo htmlentities($install_config['build_manual']); ?>" target="_blank"><?php echo htmlentities($install_config['build_manual']); ?></a></p> |
|
||||
<?php endif; ?> |
|
||||
<p class="install-success-desc">建议删除安装目录install后使用</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="other-links"> |
|
||||
<div class="back"> |
|
||||
<p class="other-links-title">您现在可以访问:</p> |
|
||||
<ul class="other-links-list"> |
|
||||
<li class="other-links-item" onclick="visitFn('admin')"> |
|
||||
<div class="other-links-pic"> |
|
||||
<img src="/install/img/web.jpg" alt=""> |
|
||||
</div> |
|
||||
<a href="javascript:void(0)" class="other-links-text" >网站后台</a> |
|
||||
</li> |
|
||||
<li class="other-links-item" onclick="visitFn('web')"> |
|
||||
<div class="other-links-pic"> |
|
||||
<img src="/install/img/site_web.png" alt=""> |
|
||||
</div> |
|
||||
<a href="javascript:void(0)" class="other-links-text" >网站电脑端</a> |
|
||||
</li> |
|
||||
<li class="other-links-item" onclick="visitFn('wap')"> |
|
||||
<div class="other-links-pic"> |
|
||||
<img src="/install/img/site_h5.png" alt=""> |
|
||||
</div> |
|
||||
<a href="javascript:void(0)" class="other-links-text" >网站手机端</a> |
|
||||
</li> |
|
||||
<?php if(!(empty($install_config['website_url']) || (($install_config['website_url'] instanceof \think\Collection || $install_config['website_url'] instanceof \think\Paginator ) && $install_config['website_url']->isEmpty()))): ?> |
|
||||
<li class="other-links-item" onclick="window.open('<?php echo htmlentities($install_config['website_url']); ?>')"> |
|
||||
<div class="other-links-pic"> |
|
||||
<img src="/install/img/admin.jpg" alt=""> |
|
||||
</div> |
|
||||
<a href="javascript:void(0)" class="other-links-text" ><?php echo htmlentities($install_config['website_name']); ?>官方网站</a> |
|
||||
</li> |
|
||||
<?php endif; ?> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
<script> |
|
||||
var index=0; |
|
||||
$(document).ready(function(){ |
|
||||
$("#education").addClass('main-hide'); |
|
||||
$("#work").addClass('main-hide'); |
|
||||
$("#social").addClass('main-hide'); |
|
||||
$('#previous_step').hide(); |
|
||||
|
|
||||
/*上一步*/ |
|
||||
$('#previous_step').bind('click', function () { |
|
||||
index--; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
/*下一步*/ |
|
||||
$('#next_step').bind('click', function () { |
|
||||
index++; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
function ControlContent(index) { |
|
||||
var stepContents = ["basicInfo","education","work","build","social"]; |
|
||||
var key;//数组中元素的索引值 |
|
||||
for (key in stepContents) { |
|
||||
var stepContent = stepContents[key];//获得元素的值 |
|
||||
if (key == index) { |
|
||||
if(stepContent=='basicInfo'){ |
|
||||
$('#previous_step').hide(); |
|
||||
}else{ |
|
||||
$('#previous_step').show(); |
|
||||
} |
|
||||
if(stepContent=='social'){ |
|
||||
$('#next_step').hide(); |
|
||||
}else{ |
|
||||
$('#next_step').show(); |
|
||||
} |
|
||||
$('#'+stepContent).removeClass('main-hide'); |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else { |
|
||||
$('#'+stepContent).addClass('main-hide'); |
|
||||
if(key>index){ |
|
||||
$('#point'+key).removeClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else if(key<index){ |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).addClass('b-select'); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function success(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 1, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
function error(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 2, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<script> |
|
||||
ControlContent(4); |
|
||||
const visitFn = (type)=>{ |
|
||||
let tips = window.localStorage.getItem('pageToLinkTips') |
|
||||
if(tips){ |
|
||||
pageToLink(type) |
|
||||
return false |
|
||||
} |
|
||||
layer.open({ |
|
||||
type: 1, // page 层类型 |
|
||||
area: ['400px', '230px'], |
|
||||
title: '提示', |
|
||||
shade: 0.6, // 遮罩透明度 |
|
||||
shadeClose: true, // 点击遮罩区域,关闭弹层 |
|
||||
anim: 0, // 0-6 的动画形式,-1 不开启 |
|
||||
content: ` |
|
||||
<div class="pop-link-wrap"> |
|
||||
<p class="link-text">首次运行,请配置伪静态,才能正常使用。</p> |
|
||||
<p class="link-text">伪静态如何配置请<a href="https://www.kancloud.cn/niushop/niushop_v6/3226724" class="other-links-text" target="_blank">参考手册</a></p> |
|
||||
<p class="link-btn"> |
|
||||
<button onclick="pageToLink('${type}')" class="layui-btn visit-btn layui-border">确定</button> |
|
||||
<button onclick="pageToLink('${type}', ${true})" class="layui-btn visit-btn layui-border">已配置,不需要在提示</button> |
|
||||
</p> |
|
||||
</div> |
|
||||
` |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
// 页面跳转 |
|
||||
function pageToLink(type,flag = false){ |
|
||||
if(flag){ |
|
||||
window.localStorage.setItem('pageToLinkTips', true) |
|
||||
} |
|
||||
if(type == 'admin'){ |
|
||||
layer.closeAll() |
|
||||
window.open('<?php echo htmlentities($root_url); ?>/admin/') |
|
||||
}else if(type == 'web'){ |
|
||||
layer.closeAll() |
|
||||
window.open('<?php echo htmlentities($root_url); ?>/web/') |
|
||||
}else if(type == 'wap'){ |
|
||||
layer.closeAll() |
|
||||
window.open('<?php echo htmlentities($root_url); ?>/wap/') |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,187 +0,0 @@ |
|||||
<?php /*a:2:{s:66:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/index/step-1.html";i:1740994438;s:58:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/base.html";i:1740994438;}*/ ?> |
|
||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
<head> |
|
||||
<meta name="renderer" content="webkit" /> |
|
||||
<meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1" /> |
|
||||
<title>安装程序 - <?php echo htmlentities($install_config['website_name']); ?></title> |
|
||||
<link rel="icon" type="image/x-icon" href="/install/img/shop_bitbug_favicon.ico" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/style.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/layui.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/common.css" /> |
|
||||
<script src="/install/js/jquery-3.1.1.js"></script> |
|
||||
<script src="/install/js/layui.js"></script> |
|
||||
|
|
||||
<script> |
|
||||
layui.use(['layer', 'upload', 'element'], function() {}); |
|
||||
</script> |
|
||||
|
|
||||
</head> |
|
||||
|
|
||||
<body> |
|
||||
<div class="head-block"> |
|
||||
<div class="top"> |
|
||||
<div class="top-logo"> |
|
||||
<div class="top-logo-img"> |
|
||||
<?php if(is_url($install_config['logo'])): ?> |
|
||||
<img src="<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php else: ?> |
|
||||
<img src="/install/img/<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php endif; ?> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="top-sub" style="flex:1;"></div> |
|
||||
<ul class="top-link"> |
|
||||
<?php if(!(empty($install_config['website_url']) || (($install_config['website_url'] instanceof \think\Collection || $install_config['website_url'] instanceof \think\Paginator ) && $install_config['website_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['website_url']); ?>" target="_blank">官方网站</a></li><?php endif; if(!(empty($install_config['bbs_url']) || (($install_config['bbs_url'] instanceof \think\Collection || $install_config['bbs_url'] instanceof \think\Paginator ) && $install_config['bbs_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['bbs_url']); ?>" target="_blank">技术论坛</a></li><?php endif; ?> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="step-content"> |
|
||||
<div style="width:1000px;margin:0 auto;"> |
|
||||
|
|
||||
<!-- 标题进度条 start--> |
|
||||
<div class="content" style="margin:30px 0 0 0;width: 100%;"> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -53px;"><span class='poetry'>1.许可协议</span></div> |
|
||||
<div id="line0" class="bar"> |
|
||||
<div id="point0" class="c-step c-select"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>2.环境检测</span></div> |
|
||||
<div id="line1" class="bar"> |
|
||||
<div id="point1" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>3.参数配置</span></div> |
|
||||
<div id="line2" class="bar"> |
|
||||
<div id="point2" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -50px;"><span class='poetry'>4.代码编译</span></div> |
|
||||
<div id="line3" class="bar"> |
|
||||
<div id="point3" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar" style="width:10px;"> |
|
||||
<div class="text" style="margin: 10px -39px;"><span class='poetry'>5.安装完成</span></div> |
|
||||
<div id="line4" class="bar" style="width: 0;"> |
|
||||
<div id="point4" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- 标题进度条 end--> |
|
||||
<div style="clear: both;"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="install-content"> |
|
||||
|
|
||||
|
|
||||
<div class="pright layui-form"> |
|
||||
<h3 class="pr-title">阅读许可协议</h3> |
|
||||
<div class="pr-agreement"> |
|
||||
<?php echo html_entity_decode($install_config['agreement']); ?> |
|
||||
</div> |
|
||||
<div class="btn-box"> |
|
||||
<div class="btn-box-text"> |
|
||||
<div class="layui-form-item"> |
|
||||
<input type="checkbox" name="readpact" id="readpact" title="我已经阅读并同意此协议" value="1" lay-skin="primary"> |
|
||||
</div> |
|
||||
</div> |
|
||||
<button class="layui-btn" lay-submit lay-filter="go">继续</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
<script> |
|
||||
var index=0; |
|
||||
$(document).ready(function(){ |
|
||||
$("#education").addClass('main-hide'); |
|
||||
$("#work").addClass('main-hide'); |
|
||||
$("#social").addClass('main-hide'); |
|
||||
$('#previous_step').hide(); |
|
||||
|
|
||||
/*上一步*/ |
|
||||
$('#previous_step').bind('click', function () { |
|
||||
index--; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
/*下一步*/ |
|
||||
$('#next_step').bind('click', function () { |
|
||||
index++; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
function ControlContent(index) { |
|
||||
var stepContents = ["basicInfo","education","work","build","social"]; |
|
||||
var key;//数组中元素的索引值 |
|
||||
for (key in stepContents) { |
|
||||
var stepContent = stepContents[key];//获得元素的值 |
|
||||
if (key == index) { |
|
||||
if(stepContent=='basicInfo'){ |
|
||||
$('#previous_step').hide(); |
|
||||
}else{ |
|
||||
$('#previous_step').show(); |
|
||||
} |
|
||||
if(stepContent=='social'){ |
|
||||
$('#next_step').hide(); |
|
||||
}else{ |
|
||||
$('#next_step').show(); |
|
||||
} |
|
||||
$('#'+stepContent).removeClass('main-hide'); |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else { |
|
||||
$('#'+stepContent).addClass('main-hide'); |
|
||||
if(key>index){ |
|
||||
$('#point'+key).removeClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else if(key<index){ |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).addClass('b-select'); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function success(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 1, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
function error(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 2, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<script> |
|
||||
layui.use('form', function () { |
|
||||
var form = layui.form; |
|
||||
|
|
||||
form.on('submit(go)', function (data) { |
|
||||
var readpact = data.field.readpact; |
|
||||
if (readpact == 1) { |
|
||||
window.location.href = '<?php echo htmlentities($root_url); ?>/install.php?step=2'; |
|
||||
} else { |
|
||||
error('您必须同意软件许可协议才能安装!'); |
|
||||
} |
|
||||
|
|
||||
}); |
|
||||
}); |
|
||||
</script> |
|
||||
|
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,491 +0,0 @@ |
|||||
<?php /*a:2:{s:66:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/index/step-3.html";i:1740994438;s:58:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/base.html";i:1740994438;}*/ ?> |
|
||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
<head> |
|
||||
<meta name="renderer" content="webkit" /> |
|
||||
<meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1" /> |
|
||||
<title>安装程序 - <?php echo htmlentities($install_config['website_name']); ?></title> |
|
||||
<link rel="icon" type="image/x-icon" href="/install/img/shop_bitbug_favicon.ico" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/style.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/layui.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/common.css" /> |
|
||||
<script src="/install/js/jquery-3.1.1.js"></script> |
|
||||
<script src="/install/js/layui.js"></script> |
|
||||
|
|
||||
<script> |
|
||||
layui.use(['layer', 'upload', 'element'], function() {}); |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
.install-content-procedure .content-procedure-item:first-of-type{ |
|
||||
background: url("/install/img/complete_two.png") no-repeat center / contain; |
|
||||
color: #fff; |
|
||||
} |
|
||||
.install-content-procedure .content-procedure-item:nth-child(2){ |
|
||||
background: url("/install/img/complete_four.png") no-repeat center / contain; |
|
||||
color: #fff; |
|
||||
} |
|
||||
.install-content-procedure .content-procedure-item:nth-child(3){ |
|
||||
background: url("/install/img/conduct.png") no-repeat center / contain; |
|
||||
color: #fff; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
</head> |
|
||||
|
|
||||
<body> |
|
||||
<div class="head-block"> |
|
||||
<div class="top"> |
|
||||
<div class="top-logo"> |
|
||||
<div class="top-logo-img"> |
|
||||
<?php if(is_url($install_config['logo'])): ?> |
|
||||
<img src="<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php else: ?> |
|
||||
<img src="/install/img/<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php endif; ?> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="top-sub" style="flex:1;"></div> |
|
||||
<ul class="top-link"> |
|
||||
<?php if(!(empty($install_config['website_url']) || (($install_config['website_url'] instanceof \think\Collection || $install_config['website_url'] instanceof \think\Paginator ) && $install_config['website_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['website_url']); ?>" target="_blank">官方网站</a></li><?php endif; if(!(empty($install_config['bbs_url']) || (($install_config['bbs_url'] instanceof \think\Collection || $install_config['bbs_url'] instanceof \think\Paginator ) && $install_config['bbs_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['bbs_url']); ?>" target="_blank">技术论坛</a></li><?php endif; ?> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="step-content"> |
|
||||
<div style="width:1000px;margin:0 auto;"> |
|
||||
|
|
||||
<!-- 标题进度条 start--> |
|
||||
<div class="content" style="margin:30px 0 0 0;width: 100%;"> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -53px;"><span class='poetry'>1.许可协议</span></div> |
|
||||
<div id="line0" class="bar"> |
|
||||
<div id="point0" class="c-step c-select"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>2.环境检测</span></div> |
|
||||
<div id="line1" class="bar"> |
|
||||
<div id="point1" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>3.参数配置</span></div> |
|
||||
<div id="line2" class="bar"> |
|
||||
<div id="point2" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -50px;"><span class='poetry'>4.代码编译</span></div> |
|
||||
<div id="line3" class="bar"> |
|
||||
<div id="point3" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar" style="width:10px;"> |
|
||||
<div class="text" style="margin: 10px -39px;"><span class='poetry'>5.安装完成</span></div> |
|
||||
<div id="line4" class="bar" style="width: 0;"> |
|
||||
<div id="point4" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- 标题进度条 end--> |
|
||||
<div style="clear: both;"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="install-content"> |
|
||||
|
|
||||
<div id='postloader' class='waitpage'></div> |
|
||||
<div class="pright layui-form"> |
|
||||
<div class="pr-title install-title layui-hide"></div> |
|
||||
<div class="pr-agreement"> |
|
||||
<form class="layui-form " id="install-form"> |
|
||||
<div class="testing parameter"> |
|
||||
<div class="testing-item"> |
|
||||
<h3>数据库设置</h3> |
|
||||
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox"> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span>数据库主机:</td> |
|
||||
<td> |
|
||||
<input name="dbhost" id="dbhost" type="text" lay-verify="empty" placeholder="请输入数据库主机" value="" class="input-txt" onChange="testDb()" /> |
|
||||
<small>一般为localhost</small> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span>Mysql端口:</td> |
|
||||
<td> |
|
||||
<input name="dbport" id="dbport" type="text" value="3306" class="input-txt" lay-verify="empty" placeholder="请输入Mysql端口"/> |
|
||||
<small>一般为3306</small> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span>数据库用户:</td> |
|
||||
<td> |
|
||||
<input name="dbuser" id="dbuser" type="text" value="" class="input-txt" onChange="testDb()" lay-verify="empty" placeholder="请输入数据库用户"/> |
|
||||
<small>默认root</small> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span>数据库密码:</td> |
|
||||
<td> |
|
||||
<div style='float:left;margin-right:3px;'> |
|
||||
<input name="dbpwd" id="dbpwd" type="text" class="input-txt" onChange="testDb()" lay-verify="empty" placeholder="请输入数据库密码" /> |
|
||||
</div> |
|
||||
<div style='float:left' class="mysql-message" id='dbpwdsta'></div> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span>数据库名称:</td> |
|
||||
<td> |
|
||||
<div style='float:left;margin-right:3px;'><input name="dbname" id="dbname" type="text" value="" class="input-txt" onChange="haveDB()" lay-verify="empty" placeholder="请输入数据库名称" /></div> |
|
||||
<div style='float:left' class="mysql-message" id='havedbsta'></div> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd">数据表前缀:</td> |
|
||||
<td> |
|
||||
<div style='float:left;margin-right:3px;'><input name="dbprefix" id="dbprefix" type="text" value="" class="input-txt" placeholder="请输入数据表前缀"/></div> |
|
||||
</td> |
|
||||
</tr> |
|
||||
|
|
||||
<tr> |
|
||||
<td class="onetd">数据库编码:</td> |
|
||||
<td> |
|
||||
<label class="install-code">UTF8</label> |
|
||||
</td> |
|
||||
</tr> |
|
||||
</table> |
|
||||
</div> |
|
||||
<div class="testing-item"> |
|
||||
<h3>网站设置</h3> |
|
||||
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox"> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span><span>网站标题:</span></td> |
|
||||
<td> |
|
||||
<input name="admin_name" id="admin_name" type="text" value="" class="input-txt" lay-verify="empty" placeholder="请输入网站标题"/> |
|
||||
<small id="mess_admin_name">网站标题 必填</small> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span><span>管理员用户名:</span></td> |
|
||||
<td> |
|
||||
<input name="username" id="username" type="text" value="" class="input-txt" lay-verify="empty" placeholder="请输入平台用户名"/> |
|
||||
<small id="mess_username">管理员用户名 必填</small> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span><span>管理员密码:</span></td> |
|
||||
<td> |
|
||||
<input name="password" id="password" type="password" value="" class="input-txt" lay-verify="empty" placeholder="请输入平台密码"/> |
|
||||
<small id="mess_password">密码 必填</small> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="onetd"><span class="required">*</span><span>确认密码:</span></td> |
|
||||
<td> |
|
||||
<input name="password2" id="password2" type="password" value="" class="input-txt" lay-verify="empty" placeholder="请输入平台确认密码"/> |
|
||||
<small id="mess_password2">确认密码 必填</small> |
|
||||
</td> |
|
||||
</tr> |
|
||||
</table> |
|
||||
<!-- <h3>默认站点</h3>--> |
|
||||
<!-- <table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox">--> |
|
||||
<!-- <tr>--> |
|
||||
<!-- <td class="onetd"><span class="required">*</span><span>站点名称:</span></td>--> |
|
||||
<!-- <td>--> |
|
||||
<!-- <input name="site_name" id="site_name" type="text" value="" class="input-txt" lay-verify="empty" placeholder="请输入站点用户名"/>--> |
|
||||
<!-- <small id="mess_site_name">站点名称 必填</small>--> |
|
||||
<!-- </td>--> |
|
||||
<!-- </tr>--> |
|
||||
<!-- <tr>--> |
|
||||
<!-- <td class="onetd"><span class="required">*</span><span>站点管理员:</span></td>--> |
|
||||
<!-- <td>--> |
|
||||
<!-- <input name="site_username" id="site_username" type="text" value="" class="input-txt" lay-verify="empty" placeholder="请输入站点用户名"/>--> |
|
||||
<!-- <small id="mess_site_username">站点管理员 必填</small>--> |
|
||||
<!-- </td>--> |
|
||||
<!-- </tr>--> |
|
||||
<!-- <div>--> |
|
||||
<!-- <td class="td-aux"></td>--> |
|
||||
<!-- <td class="td-aux"><span id="">请不要和网站管理员相同</span></td>--> |
|
||||
<!-- </div>--> |
|
||||
<!-- <tr>--> |
|
||||
<!-- <td class="onetd"><span class="required">*</span><span>管理员密码:</span></td>--> |
|
||||
<!-- <td>--> |
|
||||
<!-- <input name="site_password" id="site_password" type="password" value="" class="input-txt" lay-verify="empty" placeholder="请输入站点密码"/>--> |
|
||||
<!-- <small id="mess_site_password">管理员密码 必填</small>--> |
|
||||
<!-- </td>--> |
|
||||
<!-- </tr>--> |
|
||||
<!-- <tr>--> |
|
||||
<!-- <td class="onetd"><span class="required">*</span><span>确认密码:</span></td>--> |
|
||||
<!-- <td>--> |
|
||||
<!-- <input name="site_password2" id="site_password2" type="password" value="" class="input-txt" lay-verify="empty" placeholder="请输入站点确认密码"/>--> |
|
||||
<!-- <small id="mess_site_password2">确认密码 必填</small>--> |
|
||||
<!-- </td>--> |
|
||||
<!-- </tr>--> |
|
||||
<!-- </table>--> |
|
||||
</div> |
|
||||
</div> |
|
||||
</form> |
|
||||
|
|
||||
<div class="layui-form layui-hide testing" id="install-log"> |
|
||||
<div class="install-log"> |
|
||||
</div> |
|
||||
<div class="btn-box layui-hide"> |
|
||||
<input type="button" class="btn-back" value="后退" onclick="back()" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="btn-box"> |
|
||||
<input type="button" class="btn-back" value="后退" onclick="window.location.href='<?php echo htmlentities($root_url); ?>/install.php/index/index?step=2'" /> |
|
||||
<input type="button" class="btn-next" lay-submit lay-filter="install" value="开始安装" id="form_submit"> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
<script> |
|
||||
var index=0; |
|
||||
$(document).ready(function(){ |
|
||||
$("#education").addClass('main-hide'); |
|
||||
$("#work").addClass('main-hide'); |
|
||||
$("#social").addClass('main-hide'); |
|
||||
$('#previous_step').hide(); |
|
||||
|
|
||||
/*上一步*/ |
|
||||
$('#previous_step').bind('click', function () { |
|
||||
index--; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
/*下一步*/ |
|
||||
$('#next_step').bind('click', function () { |
|
||||
index++; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
function ControlContent(index) { |
|
||||
var stepContents = ["basicInfo","education","work","build","social"]; |
|
||||
var key;//数组中元素的索引值 |
|
||||
for (key in stepContents) { |
|
||||
var stepContent = stepContents[key];//获得元素的值 |
|
||||
if (key == index) { |
|
||||
if(stepContent=='basicInfo'){ |
|
||||
$('#previous_step').hide(); |
|
||||
}else{ |
|
||||
$('#previous_step').show(); |
|
||||
} |
|
||||
if(stepContent=='social'){ |
|
||||
$('#next_step').hide(); |
|
||||
}else{ |
|
||||
$('#next_step').show(); |
|
||||
} |
|
||||
$('#'+stepContent).removeClass('main-hide'); |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else { |
|
||||
$('#'+stepContent).addClass('main-hide'); |
|
||||
if(key>index){ |
|
||||
$('#point'+key).removeClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else if(key<index){ |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).addClass('b-select'); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function success(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 1, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
function error(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 2, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<script type="text/javascript"> |
|
||||
ControlContent(2); |
|
||||
var is_existdb = 1;//数据库是否存在 |
|
||||
var message = '数据库账号或密码不能为空'; |
|
||||
var is_install = false; |
|
||||
function inputBoxPointer(id){ |
|
||||
return document.getElementById(id); |
|
||||
} |
|
||||
layui.use('form', function(){ |
|
||||
var form = layui.form; |
|
||||
form.verify({ |
|
||||
empty: function(value, item){ //value:表单的值、item:表单的DOM对象 |
|
||||
if(value == ''){ |
|
||||
var msg = $(item).attr("placeholder"); |
|
||||
return msg; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
}); |
|
||||
form.on('submit(install)', function(data){ |
|
||||
if(is_existdb == 2){ |
|
||||
layer.confirm('数据库存在,系统将覆盖数据库!', { |
|
||||
btn: ['继续','取消'] //按钮 |
|
||||
}, function(){ |
|
||||
layer.closeAll(); |
|
||||
install(data.field); |
|
||||
|
|
||||
}, function(){ |
|
||||
layer.closeAll(); |
|
||||
return false; |
|
||||
}); |
|
||||
}else{ |
|
||||
if(is_existdb <= 0){ |
|
||||
error(message); |
|
||||
return false; |
|
||||
} |
|
||||
install(data.field); |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
//数据库连接测试 |
|
||||
function testDb() |
|
||||
{ |
|
||||
var dbhost = inputBoxPointer('dbhost').value; |
|
||||
var dbuser = inputBoxPointer('dbuser').value; |
|
||||
var dbpwd = inputBoxPointer('dbpwd').value; |
|
||||
var dbport = inputBoxPointer('dbport').value; |
|
||||
inputBoxPointer('dbpwdsta').innerHTML='<img src="/install/img/ajax-loader.gif">'; |
|
||||
|
|
||||
$.ajax({ //post也可 |
|
||||
url: '<?php echo htmlentities($root_url); ?>/install.php/index/testdb', |
|
||||
data: { dbhost: dbhost, dbport : dbport, dbuser:dbuser, dbpwd:dbpwd}, |
|
||||
type: "post", |
|
||||
dataType: 'json', |
|
||||
success: function(data){ |
|
||||
inputBoxPointer('dbpwdsta').innerHTML = data.data.message; |
|
||||
is_existdb = data.data.status; |
|
||||
message = data.data.message; |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
*验证数据库是否存在 |
|
||||
*/ |
|
||||
function haveDB() |
|
||||
{ |
|
||||
var dbhost = inputBoxPointer('dbhost').value; |
|
||||
var dbname = inputBoxPointer('dbname').value; |
|
||||
var dbuser = inputBoxPointer('dbuser').value; |
|
||||
var dbpwd = inputBoxPointer('dbpwd').value; |
|
||||
var dbport = inputBoxPointer('dbport').value; |
|
||||
inputBoxPointer('havedbsta').innerHTML='<img src="/install/img/ajax-loader.gif">'; |
|
||||
|
|
||||
$.ajax({ //post也可 |
|
||||
url: '<?php echo htmlentities($root_url); ?>/install.php/index/testdb', |
|
||||
data: { dbhost: dbhost, dbport : dbport, dbuser:dbuser, dbpwd:dbpwd,dbname:dbname}, |
|
||||
type: "post", |
|
||||
dataType: 'json', |
|
||||
success: function(data){ |
|
||||
inputBoxPointer('havedbsta').innerHTML = data.data.message; |
|
||||
is_existdb = data.data.status; |
|
||||
message = data.data.message; |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function getStatus() { |
|
||||
$.ajax({ |
|
||||
url: "<?php echo htmlentities($root_url); ?>/install.php/index/getInstallInfo", |
|
||||
dataType: 'json', |
|
||||
type: 'get', |
|
||||
success : function(data) { |
|
||||
if(data.code == 1) { |
|
||||
$(data.data.log).each(function (i, e){ |
|
||||
if($('.log-'+i).length == 0) { |
|
||||
let html = `<div class="log-${i}"> |
|
||||
<span>${e[0]}${e[1] == 'success' ? "成功" : ""}</span> |
|
||||
<span>${e[2]}</span> |
|
||||
</div>`; |
|
||||
$('.install-log').append(html); |
|
||||
SetScroll(); |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
if(data.data.status == 0 || data.data.status == 1) { |
|
||||
setTimeout(() => { |
|
||||
getStatus(); |
|
||||
}, 200) |
|
||||
}else{ |
|
||||
$('#install-log .btn-box').removeClass('layui-hide') |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
function install(data){ |
|
||||
if(is_install) return false; |
|
||||
|
|
||||
$('#install-form').addClass('layui-hide') |
|
||||
$('#install-log').removeClass('layui-hide') |
|
||||
// $('.install-log').html('<div class="install-head">正在安装...</div>'); |
|
||||
$('.install-title').removeClass('layui-hide') |
|
||||
$('.install-title').html('<div class="install-head">正在安装...</div>'); |
|
||||
$('.pright>.btn-box').addClass('layui-hide') |
|
||||
is_install = true; |
|
||||
$.ajax({ |
|
||||
url: "<?php echo htmlentities($root_url); ?>/install.php/index/install", |
|
||||
data: data, |
|
||||
dataType: 'json', |
|
||||
type: 'post', |
|
||||
success : function(res) { |
|
||||
layer.close(index); |
|
||||
if(res.code == 1){ |
|
||||
$.ajax({ |
|
||||
url: "<?php echo htmlentities($root_url); ?>/install.php/index/initData", |
|
||||
data: data, |
|
||||
dataType: 'json', |
|
||||
type: 'post', |
|
||||
success : function(data) { |
|
||||
if(data.code == 1){ |
|
||||
window.location.href = '<?php echo htmlentities($root_url); ?>/install.php/index/build'; |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
}else{ |
|
||||
error(res.msg); |
|
||||
is_install = false; |
|
||||
} |
|
||||
}, |
|
||||
}) |
|
||||
setTimeout(() => { |
|
||||
getStatus(); |
|
||||
}, 500) |
|
||||
} |
|
||||
function back(){ |
|
||||
$('#install-form').removeClass('layui-hide') |
|
||||
$('#install-log').addClass('layui-hide') |
|
||||
$('.install-title').addClass('layui-hide') |
|
||||
$('.pright>.btn-box').removeClass('layui-hide') |
|
||||
} |
|
||||
|
|
||||
window.onload = SetScroll; |
|
||||
function SetScroll(){ |
|
||||
var height=$(".install-log")[0].scrollHeight; |
|
||||
$(".install-log").scrollTop(height); |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,218 +0,0 @@ |
|||||
<?php /*a:2:{s:66:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/index/step-2.html";i:1740994438;s:58:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/base.html";i:1740994438;}*/ ?> |
|
||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
<head> |
|
||||
<meta name="renderer" content="webkit" /> |
|
||||
<meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1" /> |
|
||||
<title>安装程序 - <?php echo htmlentities($install_config['website_name']); ?></title> |
|
||||
<link rel="icon" type="image/x-icon" href="/install/img/shop_bitbug_favicon.ico" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/style.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/layui.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/common.css" /> |
|
||||
<script src="/install/js/jquery-3.1.1.js"></script> |
|
||||
<script src="/install/js/layui.js"></script> |
|
||||
|
|
||||
<script> |
|
||||
layui.use(['layer', 'upload', 'element'], function() {}); |
|
||||
</script> |
|
||||
|
|
||||
|
|
||||
|
|
||||
</head> |
|
||||
|
|
||||
<body> |
|
||||
<div class="head-block"> |
|
||||
<div class="top"> |
|
||||
<div class="top-logo"> |
|
||||
<div class="top-logo-img"> |
|
||||
<?php if(is_url($install_config['logo'])): ?> |
|
||||
<img src="<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php else: ?> |
|
||||
<img src="/install/img/<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php endif; ?> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="top-sub" style="flex:1;"></div> |
|
||||
<ul class="top-link"> |
|
||||
<?php if(!(empty($install_config['website_url']) || (($install_config['website_url'] instanceof \think\Collection || $install_config['website_url'] instanceof \think\Paginator ) && $install_config['website_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['website_url']); ?>" target="_blank">官方网站</a></li><?php endif; if(!(empty($install_config['bbs_url']) || (($install_config['bbs_url'] instanceof \think\Collection || $install_config['bbs_url'] instanceof \think\Paginator ) && $install_config['bbs_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['bbs_url']); ?>" target="_blank">技术论坛</a></li><?php endif; ?> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="step-content"> |
|
||||
<div style="width:1000px;margin:0 auto;"> |
|
||||
|
|
||||
<!-- 标题进度条 start--> |
|
||||
<div class="content" style="margin:30px 0 0 0;width: 100%;"> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -53px;"><span class='poetry'>1.许可协议</span></div> |
|
||||
<div id="line0" class="bar"> |
|
||||
<div id="point0" class="c-step c-select"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>2.环境检测</span></div> |
|
||||
<div id="line1" class="bar"> |
|
||||
<div id="point1" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>3.参数配置</span></div> |
|
||||
<div id="line2" class="bar"> |
|
||||
<div id="point2" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -50px;"><span class='poetry'>4.代码编译</span></div> |
|
||||
<div id="line3" class="bar"> |
|
||||
<div id="point3" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar" style="width:10px;"> |
|
||||
<div class="text" style="margin: 10px -39px;"><span class='poetry'>5.安装完成</span></div> |
|
||||
<div id="line4" class="bar" style="width: 0;"> |
|
||||
<div id="point4" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- 标题进度条 end--> |
|
||||
<div style="clear: both;"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="install-content"> |
|
||||
|
|
||||
<div class="pright layui-form"> |
|
||||
<div class="pr-agreement"> |
|
||||
<h3>系统环境检测<span class="desc">系统环境要求必须满足下列所有条件,否则系统或系统部份功能将无法使用。</span></h3> |
|
||||
<div class="testing-item"> |
|
||||
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox"> |
|
||||
<tr> |
|
||||
<th width="30%" align="center"><strong>需开启的变量或函数</strong></th> |
|
||||
<th width="35%"><strong>要求</strong></th> |
|
||||
<th width="35%"><strong>实际状态及建议</strong></th> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td>php版本</td> |
|
||||
<td style="color:#409eff;">php8.0.0及以上 </td> |
|
||||
<td><font color=<?php if($verison): ?>#409eff<?php else: ?>red<?php endif; ?>><?php echo htmlentities($phpv); ?></font> </td> |
|
||||
</tr> |
|
||||
<?php foreach($system_variables as $variables_key => $variables_item): ?> |
|
||||
<tr> |
|
||||
<td><?php echo htmlentities($variables_item['name']); ?></td> |
|
||||
<td><?php echo htmlentities($variables_item['need']); ?></td> |
|
||||
<td><img clsss="check-icon" src="<?php if($variables_item['status']): ?>/install/img/success.png<?php else: ?>/install/img/error.png<?php endif; ?>"/></td> |
|
||||
</tr> |
|
||||
<?php endforeach; ?> |
|
||||
</table> |
|
||||
</div> |
|
||||
<h3>目录权限检测<span class="desc">系统要求必须满足下列所有的目录权限全部可读写的需求才能使用,其它应用目录可安装后在管理后台检测。</span></h3> |
|
||||
<div class="testing-item"> |
|
||||
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox"> |
|
||||
<tr> |
|
||||
<th width="30%" align="center"><strong>目录名</strong></th> |
|
||||
<th width="35%"><strong>读取权限</strong></th> |
|
||||
<th width="35%"><strong>写入权限</strong></th> |
|
||||
</tr> |
|
||||
<?php foreach($dirs_list as $dirs_key => $dirs_item): ?> |
|
||||
<tr> |
|
||||
<td><?php echo htmlentities($dirs_item['path_name']); ?></td> |
|
||||
<td> |
|
||||
<img clsss="check-icon" src="<?php if($dirs_item['is_readable']): ?>/install/img/success.png<?php else: ?>/install/img/error.png<?php endif; ?>"/> |
|
||||
</td> |
|
||||
<td> |
|
||||
<img clsss="check-icon" src="<?php if($dirs_item['is_write']): ?>/install/img/success.png<?php else: ?>/install/img/error.png<?php endif; ?>"/> |
|
||||
</td> |
|
||||
</tr> |
|
||||
<?php endforeach; ?> |
|
||||
|
|
||||
</table> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="btn-box"> |
|
||||
<input type="button" class="btn-back" value="后退" onclick="window.location.href = '<?php echo htmlentities($root_url); ?>/install.php/index/index?step=1';" /> |
|
||||
<input type="button" class="btn-next" value="继续" <?php if(!$continue): ?> style="background-color:#777;color:#FFF;" disabled="disabled"<?php endif; ?> onclick="window.location.href = '<?php echo htmlentities($root_url); ?>/install.php/index/index?step=3';" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="testing"> |
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
<script> |
|
||||
var index=0; |
|
||||
$(document).ready(function(){ |
|
||||
$("#education").addClass('main-hide'); |
|
||||
$("#work").addClass('main-hide'); |
|
||||
$("#social").addClass('main-hide'); |
|
||||
$('#previous_step').hide(); |
|
||||
|
|
||||
/*上一步*/ |
|
||||
$('#previous_step').bind('click', function () { |
|
||||
index--; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
/*下一步*/ |
|
||||
$('#next_step').bind('click', function () { |
|
||||
index++; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
function ControlContent(index) { |
|
||||
var stepContents = ["basicInfo","education","work","build","social"]; |
|
||||
var key;//数组中元素的索引值 |
|
||||
for (key in stepContents) { |
|
||||
var stepContent = stepContents[key];//获得元素的值 |
|
||||
if (key == index) { |
|
||||
if(stepContent=='basicInfo'){ |
|
||||
$('#previous_step').hide(); |
|
||||
}else{ |
|
||||
$('#previous_step').show(); |
|
||||
} |
|
||||
if(stepContent=='social'){ |
|
||||
$('#next_step').hide(); |
|
||||
}else{ |
|
||||
$('#next_step').show(); |
|
||||
} |
|
||||
$('#'+stepContent).removeClass('main-hide'); |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else { |
|
||||
$('#'+stepContent).addClass('main-hide'); |
|
||||
if(key>index){ |
|
||||
$('#point'+key).removeClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else if(key<index){ |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).addClass('b-select'); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function success(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 1, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
function error(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 2, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<script> |
|
||||
ControlContent(1); |
|
||||
</script> |
|
||||
|
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,525 +0,0 @@ |
|||||
<?php /*a:2:{s:66:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/index/step-4.html";i:1740994438;s:58:"/www/wwwroot/hnhbty.cn/niucloud/app/install/view/base.html";i:1740994438;}*/ ?> |
|
||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
<head> |
|
||||
<meta name="renderer" content="webkit" /> |
|
||||
<meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1" /> |
|
||||
<title>安装程序 - <?php echo htmlentities($install_config['website_name']); ?></title> |
|
||||
<link rel="icon" type="image/x-icon" href="/install/img/shop_bitbug_favicon.ico" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/style.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/layui.css" /> |
|
||||
<link rel="stylesheet" type="text/css" href="/install/css/common.css" /> |
|
||||
<script src="/install/js/jquery-3.1.1.js"></script> |
|
||||
<script src="/install/js/layui.js"></script> |
|
||||
|
|
||||
<script> |
|
||||
layui.use(['layer', 'upload', 'element'], function() {}); |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
.layui-layer-title { |
|
||||
border-bottom: 0!important; |
|
||||
} |
|
||||
.auth-layer { |
|
||||
padding: 20px; |
|
||||
} |
|
||||
.auth-layer .layui-form-item { |
|
||||
margin-bottom: 18px; |
|
||||
position: relative; |
|
||||
} |
|
||||
.auth-layer .layui-form-item .error { |
|
||||
color: red; |
|
||||
font-size: 12px; |
|
||||
position: absolute; |
|
||||
line-height: 1; |
|
||||
top: 42px; |
|
||||
display: none; |
|
||||
} |
|
||||
.auth-layer .layui-form-item button,.auth-layer .layui-form-item .layui-input { |
|
||||
height: 40px; |
|
||||
width: 100%; |
|
||||
} |
|
||||
.auth-layer .layui-form-item .layui-word-aux { |
|
||||
line-height: 1; |
|
||||
} |
|
||||
.auth-layer .to-buy { |
|
||||
text-align: right; |
|
||||
} |
|
||||
.auth-layer .to-buy a { |
|
||||
height: 40px; |
|
||||
line-height: 40px; |
|
||||
color: #409eff; |
|
||||
border: 1px solid #409eff; |
|
||||
display:block; |
|
||||
text-align: center; |
|
||||
border-radius: 2px; |
|
||||
} |
|
||||
.auth-layer .link { |
|
||||
text-align: right; |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
.auth-layer .link a { |
|
||||
color: #409eff; |
|
||||
} |
|
||||
.build-warp { |
|
||||
margin-left: 50px; |
|
||||
padding: 20px; |
|
||||
margin-right: 50px; |
|
||||
background: #F7F9FA; |
|
||||
border-radius: 5px; |
|
||||
height: 60vh; |
|
||||
overflow-y: scroll; |
|
||||
} |
|
||||
.build-warp::-webkit-scrollbar { |
|
||||
width: 6px; |
|
||||
border-radius: 4px; |
|
||||
} |
|
||||
.build-warp::-webkit-scrollbar-track { |
|
||||
background-color: rgba(0, 0, 0, 0.1); |
|
||||
} |
|
||||
.build-warp::-webkit-scrollbar-thumb { |
|
||||
background-color: rgba(0, 0, 0, 0.3); |
|
||||
border-radius: 4px; |
|
||||
} |
|
||||
.build-warp .msg-item { |
|
||||
margin: 20px 0; |
|
||||
} |
|
||||
.build-warp .msg-item p { |
|
||||
white-space: pre-wrap; |
|
||||
font-size: 13px; |
|
||||
font-family: Monaco,Menlo,Consolas,monospace; |
|
||||
} |
|
||||
.build-log .msg-item:first-child { |
|
||||
margin-top: 0; |
|
||||
} |
|
||||
.build-warp .msg-item .symbol { |
|
||||
margin-right: 10px; |
|
||||
} |
|
||||
.build-warp .msg-item .error { |
|
||||
background-color: #c0392b; |
|
||||
margin-right: 10px; |
|
||||
padding: 2px 3px; |
|
||||
color: #fff; |
|
||||
line-height: 1; |
|
||||
font-size: 12px; |
|
||||
} |
|
||||
.build-warp .build-progress { |
|
||||
display: none; |
|
||||
} |
|
||||
</style> |
|
||||
|
|
||||
</head> |
|
||||
|
|
||||
<body> |
|
||||
<div class="head-block"> |
|
||||
<div class="top"> |
|
||||
<div class="top-logo"> |
|
||||
<div class="top-logo-img"> |
|
||||
<?php if(is_url($install_config['logo'])): ?> |
|
||||
<img src="<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php else: ?> |
|
||||
<img src="/install/img/<?php echo htmlentities($install_config['logo']); ?>"> |
|
||||
<?php endif; ?> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="top-sub" style="flex:1;"></div> |
|
||||
<ul class="top-link"> |
|
||||
<?php if(!(empty($install_config['website_url']) || (($install_config['website_url'] instanceof \think\Collection || $install_config['website_url'] instanceof \think\Paginator ) && $install_config['website_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['website_url']); ?>" target="_blank">官方网站</a></li><?php endif; if(!(empty($install_config['bbs_url']) || (($install_config['bbs_url'] instanceof \think\Collection || $install_config['bbs_url'] instanceof \think\Paginator ) && $install_config['bbs_url']->isEmpty()))): ?><li><a href="<?php echo htmlentities($install_config['bbs_url']); ?>" target="_blank">技术论坛</a></li><?php endif; ?> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="step-content"> |
|
||||
<div style="width:1000px;margin:0 auto;"> |
|
||||
|
|
||||
<!-- 标题进度条 start--> |
|
||||
<div class="content" style="margin:30px 0 0 0;width: 100%;"> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -53px;"><span class='poetry'>1.许可协议</span></div> |
|
||||
<div id="line0" class="bar"> |
|
||||
<div id="point0" class="c-step c-select"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>2.环境检测</span></div> |
|
||||
<div id="line1" class="bar"> |
|
||||
<div id="point1" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -58px;"><span class='poetry'>3.参数配置</span></div> |
|
||||
<div id="line2" class="bar"> |
|
||||
<div id="point2" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar"> |
|
||||
<div class="text" style="margin: 10px -50px;"><span class='poetry'>4.代码编译</span></div> |
|
||||
<div id="line3" class="bar"> |
|
||||
<div id="point3" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="processBar" style="width:10px;"> |
|
||||
<div class="text" style="margin: 10px -39px;"><span class='poetry'>5.安装完成</span></div> |
|
||||
<div id="line4" class="bar" style="width: 0;"> |
|
||||
<div id="point4" class="c-step"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<!-- 标题进度条 end--> |
|
||||
<div style="clear: both;"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="install-content"> |
|
||||
|
|
||||
<div class="build-warp"> |
|
||||
<div class="build-log"></div> |
|
||||
<div class="build-progress"> |
|
||||
<div class="msg-item"> |
|
||||
<span class="symbol"> > </span> |
|
||||
<span class="content"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="other-links"></div> |
|
||||
|
|
||||
<template id="authLayer"> |
|
||||
<div class="layui-form auth-layer"> |
|
||||
<div class="bind-auth layui-hide"> |
|
||||
<div class="layui-form-item"> |
|
||||
<input type="text" name="auth_code" placeholder="请输入授权码" autocomplete="off" class="layui-input"> |
|
||||
<div class="error">请输入授权码</div> |
|
||||
</div> |
|
||||
<div class="layui-form-item"> |
|
||||
<input type="text" name="auth_secret" placeholder="请输入授权秘钥" autocomplete="off" class="layui-input"> |
|
||||
<div class="error">请输入授权秘钥</div> |
|
||||
</div> |
|
||||
<div class="layui-form-item"> |
|
||||
<button class="layui-btn" lay-submit lay-filter="authInfoForm">立即绑定</button> |
|
||||
</div> |
|
||||
<div class="layui-form-item to-buy"> |
|
||||
<a href="javascript:;" onclick="prev()">返回上一步</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="options"> |
|
||||
<div class="layui-form-item"> |
|
||||
<button class="layui-btn" onclick="toBindAuthCode()">已授权,立即绑定授权</button> |
|
||||
</div> |
|
||||
<div class="layui-form-item to-buy"> |
|
||||
<a href="javascript:;" onclick="installSuccess(0)" target="_blank">我是开发者,自行编译</a> |
|
||||
</div> |
|
||||
<div class="layui-form-item to-buy"> |
|
||||
<a href="javascript:;" onclick="applyExperience()" style="color:#21ba45;border-color:#21ba45;">立即安装使用免费版</a> |
|
||||
</div> |
|
||||
<?php if(!(empty($install_config['build_manual']) || (($install_config['build_manual'] instanceof \think\Collection || $install_config['build_manual'] instanceof \think\Paginator ) && $install_config['build_manual']->isEmpty()))): ?> |
|
||||
<div class="layui-form-item link"> |
|
||||
<a href="<?php echo htmlentities($install_config['build_manual']); ?>" target="_blank">安装帮助指引</a> |
|
||||
</div> |
|
||||
<?php endif; ?> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
</div> |
|
||||
|
|
||||
<script> |
|
||||
var index=0; |
|
||||
$(document).ready(function(){ |
|
||||
$("#education").addClass('main-hide'); |
|
||||
$("#work").addClass('main-hide'); |
|
||||
$("#social").addClass('main-hide'); |
|
||||
$('#previous_step').hide(); |
|
||||
|
|
||||
/*上一步*/ |
|
||||
$('#previous_step').bind('click', function () { |
|
||||
index--; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
/*下一步*/ |
|
||||
$('#next_step').bind('click', function () { |
|
||||
index++; |
|
||||
ControlContent(index); |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
function ControlContent(index) { |
|
||||
var stepContents = ["basicInfo","education","work","build","social"]; |
|
||||
var key;//数组中元素的索引值 |
|
||||
for (key in stepContents) { |
|
||||
var stepContent = stepContents[key];//获得元素的值 |
|
||||
if (key == index) { |
|
||||
if(stepContent=='basicInfo'){ |
|
||||
$('#previous_step').hide(); |
|
||||
}else{ |
|
||||
$('#previous_step').show(); |
|
||||
} |
|
||||
if(stepContent=='social'){ |
|
||||
$('#next_step').hide(); |
|
||||
}else{ |
|
||||
$('#next_step').show(); |
|
||||
} |
|
||||
$('#'+stepContent).removeClass('main-hide'); |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else { |
|
||||
$('#'+stepContent).addClass('main-hide'); |
|
||||
if(key>index){ |
|
||||
$('#point'+key).removeClass('c-select'); |
|
||||
$('#line'+key).removeClass('b-select'); |
|
||||
}else if(key<index){ |
|
||||
$('#point'+key).addClass('c-select'); |
|
||||
$('#line'+key).addClass('b-select'); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function success(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 1, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
function error(message){ |
|
||||
layer.alert(message, { |
|
||||
icon: 2, |
|
||||
skin: 'layer-ext-moon', |
|
||||
title:'提示' |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<script> |
|
||||
ControlContent(3); |
|
||||
|
|
||||
const REQUEST_HEADER = { token: '<?php echo htmlentities($token); ?>' } |
|
||||
var authinfo = null |
|
||||
var form = null |
|
||||
var submitTag = false |
|
||||
|
|
||||
layui.use('form', function(){ |
|
||||
form = layui.form; |
|
||||
|
|
||||
form.on('submit(authInfoForm)', function(data){ |
|
||||
var isVerify = true |
|
||||
if ($('[name="auth_code"]').val() == '') { |
|
||||
$('[name="auth_code"]').next().show() |
|
||||
isVerify = false |
|
||||
} else { |
|
||||
$('[name="auth_code"]').next().hide() |
|
||||
} |
|
||||
if ($('[name="auth_secret"]').val() == '') { |
|
||||
$('[name="auth_secret"]').next().show() |
|
||||
isVerify = false |
|
||||
} else { |
|
||||
$('[name="auth_secret"]').next().hide() |
|
||||
} |
|
||||
isVerify && bindAuthCode() |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
function toBindAuthCode() { |
|
||||
$('.bind-auth').removeClass('layui-hide') |
|
||||
$('.options').addClass('layui-hide') |
|
||||
} |
|
||||
|
|
||||
function prev() { |
|
||||
$('.bind-auth').addClass('layui-hide') |
|
||||
$('.options').removeClass('layui-hide') |
|
||||
} |
|
||||
|
|
||||
function bindAuthCode() { |
|
||||
if (submitTag) return |
|
||||
submitTag = true |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: '<?php echo htmlentities($root_url); ?>/index.php/adminapi/niucloud/authinfo', |
|
||||
headers: REQUEST_HEADER, |
|
||||
data: { |
|
||||
auth_code: $('[name="auth_code"]').val(), |
|
||||
auth_secret: $('[name="auth_secret"]').val() |
|
||||
}, |
|
||||
type: "post", |
|
||||
dataType: 'json', |
|
||||
success: function(res){ |
|
||||
if (res.code) { |
|
||||
layer.closeAll() |
|
||||
$('.build-progress').show() |
|
||||
getCloudBuildTask() |
|
||||
} else { |
|
||||
layer.msg(res.msg) |
|
||||
} |
|
||||
submitTag = false |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
function applyExperience() { |
|
||||
if (submitTag) return |
|
||||
submitTag = true |
|
||||
|
|
||||
$.ajax({ |
|
||||
url: '<?php echo htmlentities($root_url); ?>/index.php/adminapi/niucloud/apply/experience', |
|
||||
headers: REQUEST_HEADER, |
|
||||
type: "get", |
|
||||
dataType: 'json', |
|
||||
success: function(res){ |
|
||||
if (res.code) { |
|
||||
layer.closeAll() |
|
||||
$('.build-progress').show() |
|
||||
getCloudBuildTask() |
|
||||
} else { |
|
||||
layer.msg(res.msg) |
|
||||
} |
|
||||
submitTag = false |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
// 获取授权信息 |
|
||||
function getAuthinfo() { |
|
||||
$.ajax({ |
|
||||
url: '<?php echo htmlentities($root_url); ?>/index.php/adminapi/niucloud/authinfo', |
|
||||
headers: REQUEST_HEADER, |
|
||||
type: "get", |
|
||||
async: false, |
|
||||
dataType: 'json', |
|
||||
success: function(res){ |
|
||||
if (res.code && res.data) { |
|
||||
getCloudBuildTask() |
|
||||
} else { |
|
||||
showAuthLayer() |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
getAuthinfo() |
|
||||
|
|
||||
function showAuthLayer() { |
|
||||
layer.open({ |
|
||||
type: 1, |
|
||||
title: '绑定授权码云编译', |
|
||||
area: ['400px'], |
|
||||
content: $('#authLayer').html(), |
|
||||
btn: [], |
|
||||
closeBtn: false |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
function installSuccess(isBuild = 1) { |
|
||||
window.location.href = '<?php echo htmlentities($root_url); ?>/install.php/index/installSuccess' + (isBuild ? '' : '?is_build=0'); |
|
||||
} |
|
||||
|
|
||||
function buildProgress() { |
|
||||
const frames = makeIterator(['/', '—', '\\', '|']) |
|
||||
setInterval(() => { |
|
||||
$('.build-progress .content').text(frames.next().value) |
|
||||
}, 150) |
|
||||
} |
|
||||
buildProgress() |
|
||||
|
|
||||
function makeIterator(array) { |
|
||||
var nextIndex = 0 |
|
||||
return { |
|
||||
next() { |
|
||||
if ((nextIndex + 1) == array.length) { |
|
||||
nextIndex = 0 |
|
||||
} |
|
||||
return { value: array[nextIndex++] } |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function getCloudBuildTask() { |
|
||||
$.ajax({ |
|
||||
url: '<?php echo htmlentities($root_url); ?>/index.php/adminapi/niucloud/build', |
|
||||
headers: REQUEST_HEADER, |
|
||||
type: "get", |
|
||||
dataType: 'json', |
|
||||
success: function(res){ |
|
||||
if (res.data) { |
|
||||
getCloudBuildLog() |
|
||||
} else { |
|
||||
cloudBuild() |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
var cloudBuildLog = [] |
|
||||
function getCloudBuildLog() { |
|
||||
$.ajax({ |
|
||||
url: '<?php echo htmlentities($root_url); ?>/index.php/adminapi/niucloud/build/log', |
|
||||
headers: REQUEST_HEADER, |
|
||||
type: "get", |
|
||||
dataType: 'json', |
|
||||
success: function(res){ |
|
||||
if (!res.data) { |
|
||||
if (cloudBuildLog.length) { |
|
||||
installSuccess() |
|
||||
} |
|
||||
return |
|
||||
} |
|
||||
const data = res.data.data ?? [] |
|
||||
let error = '' |
|
||||
|
|
||||
if (data[0] && data[0].length) { |
|
||||
if (cloudBuildLog.length == 0) { |
|
||||
$('.build-progress').show() |
|
||||
$('.build-log').html('') |
|
||||
} |
|
||||
|
|
||||
data[0].forEach(item => { |
|
||||
if (!cloudBuildLog.includes(item.action)) { |
|
||||
$('.build-log').append(`<div class="msg-item"><span class="symbol"> > </span><span class="content">正在执行:${item.action}</span></div>`) |
|
||||
cloudBuildLog.push(item.action) |
|
||||
|
|
||||
if (item.code == 0) { |
|
||||
error = item.msg |
|
||||
$('.build-log').append(`<div class="msg-item"><span class="symbol"> > </span><span class="error">error</span><span class="content">${item.msg}</span></div>`) |
|
||||
$('.build-log').append(`<div class="msg-item"><span class="symbol"> > </span><span class="content">编译失败请不要关闭当前页面,请访问官方网站联系客服解决处理问题</span></div>`) |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
if (error) { |
|
||||
$('.build-progress').hide() |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
setTimeout(() => { |
|
||||
getCloudBuildLog() |
|
||||
}, 2000) |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
function cloudBuild() { |
|
||||
$.ajax({ |
|
||||
url: '<?php echo htmlentities($root_url); ?>/index.php/adminapi/niucloud/build/install', |
|
||||
headers: REQUEST_HEADER, |
|
||||
type: "post", |
|
||||
dataType: 'json', |
|
||||
success: function(res){ |
|
||||
if (res.code) { |
|
||||
getCloudBuildLog() |
|
||||
} else { |
|
||||
if (res.msg.indexOf('队列') != -1) { |
|
||||
$('.build-log').append(`<div class="msg-item"><span class="symbol"> > </span><span class="content">一键云安装小程序队列任务过多,请耐心等待</span></div>`) |
|
||||
setTimeout(function (){ |
|
||||
cloudBuild() |
|
||||
}, 10000) |
|
||||
} else { |
|
||||
$('.build-log').append(`<div class="msg-item"><span class="symbol"> > </span><span class="error">error</span><span class="content">${res.msg}</span></div>`) |
|
||||
$('.build-log').append(`<div class="msg-item"><span class="symbol"> > </span><span class="content">编译失败请不要关闭当前页面,请访问官方网站联系客服解决处理问题</span></div>`) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,25 +0,0 @@ |
|||||
<?php /*a:1:{s:53:"/www/wwwroot/hnhbty.cn/niucloud/public/wap/index.html";i:1747194084;}*/ ?> |
|
||||
<!DOCTYPE html> |
|
||||
<html lang="zh-cn"> |
|
||||
<head> |
|
||||
<link rel="stylesheet" href="/wap/assets/uni.dbb3df19.css"> |
|
||||
|
|
||||
<meta charset="UTF-8" /> |
|
||||
<script> |
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
|
||||
CSS.supports('top: constant(a)')) |
|
||||
document.write( |
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
|
||||
</script> |
|
||||
<title></title> |
|
||||
<!--preload-links--> |
|
||||
<!--app-context--> |
|
||||
<script type="module" crossorigin src="/wap/assets/index-ed377420.js"></script> |
|
||||
<link rel="stylesheet" href="/wap/assets/index-5d848bf4.css"> |
|
||||
</head> |
|
||||
<body> |
|
||||
<div id="app"><!--app-html--></div> |
|
||||
|
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,16 +0,0 @@ |
|||||
<?php /*a:1:{s:55:"/www/wwwroot/hnhbty.cn/niucloud/public/admin/index.html";i:1747194084;}*/ ?> |
|
||||
<!DOCTYPE html> |
|
||||
<html lang="zh-cn"> |
|
||||
<head> |
|
||||
<meta charset="UTF-8" /> |
|
||||
<link rel="icon" type="image" href="/admin/niucloud.ico" /> |
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
||||
<title></title> |
|
||||
<script type="module" crossorigin src="/admin/assets/index-1dc7b228.js"></script> |
|
||||
<link rel="stylesheet" href="/admin/assets/index-8222cd06.css"> |
|
||||
</head> |
|
||||
<body> |
|
||||
<div id="app"></div> |
|
||||
|
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,3 +0,0 @@ |
|||||
.idea |
|
||||
vendor/ |
|
||||
composer.lock |
|
||||
@ -1,35 +0,0 @@ |
|||||
This help guides Huawei engineers to add or modify the license announcement |
|
||||
during the development. |
|
||||
|
|
||||
In the case that you add a new file, the text below should be added in the head. |
|
||||
Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
|
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
this file except in compliance with the License. You may obtain a copy of the |
|
||||
License at |
|
||||
|
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
|
|
||||
Unless required by applicable law or agreed to in writing, software distributed |
|
||||
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
specific language governing permissions and limitations under the License. |
|
||||
|
|
||||
|
|
||||
In the case that you modify one existing file, the text below should be added after |
|
||||
the exiting license. |
|
||||
Huawei has modified this source file. |
|
||||
|
|
||||
Copyright 2019 Huawei Technologies Co., Ltd. |
|
||||
|
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not |
|
||||
use this file except in compliance with the License. You may obtain a copy of |
|
||||
the License at |
|
||||
|
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
|
|
||||
Unless required by applicable law or agreed to in writing, software |
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
||||
License for the specific language governing permissions and limitations under |
|
||||
the License. |
|
||||
@ -1,201 +0,0 @@ |
|||||
Apache License |
|
||||
Version 2.0, January 2004 |
|
||||
http://www.apache.org/licenses/ |
|
||||
|
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|
||||
|
|
||||
1. Definitions. |
|
||||
|
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
|
||||
and distribution as defined by Sections 1 through 9 of this document. |
|
||||
|
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
|
||||
the copyright owner that is granting the License. |
|
||||
|
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
|
||||
other entities that control, are controlled by, or are under common |
|
||||
control with that entity. For the purposes of this definition, |
|
||||
"control" means (i) the power, direct or indirect, to cause the |
|
||||
direction or management of such entity, whether by contract or |
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
|
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
|
||||
|
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
|
||||
exercising permissions granted by this License. |
|
||||
|
|
||||
"Source" form shall mean the preferred form for making modifications, |
|
||||
including but not limited to software source code, documentation |
|
||||
source, and configuration files. |
|
||||
|
|
||||
"Object" form shall mean any form resulting from mechanical |
|
||||
transformation or translation of a Source form, including but |
|
||||
not limited to compiled object code, generated documentation, |
|
||||
and conversions to other media types. |
|
||||
|
|
||||
"Work" shall mean the work of authorship, whether in Source or |
|
||||
Object form, made available under the License, as indicated by a |
|
||||
copyright notice that is included in or attached to the work |
|
||||
(an example is provided in the Appendix below). |
|
||||
|
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
|
||||
form, that is based on (or derived from) the Work and for which the |
|
||||
editorial revisions, annotations, elaborations, or other modifications |
|
||||
represent, as a whole, an original work of authorship. For the purposes |
|
||||
of this License, Derivative Works shall not include works that remain |
|
||||
separable from, or merely link (or bind by name) to the interfaces of, |
|
||||
the Work and Derivative Works thereof. |
|
||||
|
|
||||
"Contribution" shall mean any work of authorship, including |
|
||||
the original version of the Work and any modifications or additions |
|
||||
to that Work or Derivative Works thereof, that is intentionally |
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
|
||||
or by an individual or Legal Entity authorized to submit on behalf of |
|
||||
the copyright owner. For the purposes of this definition, "submitted" |
|
||||
means any form of electronic, verbal, or written communication sent |
|
||||
to the Licensor or its representatives, including but not limited to |
|
||||
communication on electronic mailing lists, source code control systems, |
|
||||
and issue tracking systems that are managed by, or on behalf of, the |
|
||||
Licensor for the purpose of discussing and improving the Work, but |
|
||||
excluding communication that is conspicuously marked or otherwise |
|
||||
designated in writing by the copyright owner as "Not a Contribution." |
|
||||
|
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
|
||||
on behalf of whom a Contribution has been received by Licensor and |
|
||||
subsequently incorporated within the Work. |
|
||||
|
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
|
||||
this License, each Contributor hereby grants to You a perpetual, |
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|
||||
copyright license to reproduce, prepare Derivative Works of, |
|
||||
publicly display, publicly perform, sublicense, and distribute the |
|
||||
Work and such Derivative Works in Source or Object form. |
|
||||
|
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
|
||||
this License, each Contributor hereby grants to You a perpetual, |
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|
||||
(except as stated in this section) patent license to make, have made, |
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
|
||||
where such license applies only to those patent claims licensable |
|
||||
by such Contributor that are necessarily infringed by their |
|
||||
Contribution(s) alone or by combination of their Contribution(s) |
|
||||
with the Work to which such Contribution(s) was submitted. If You |
|
||||
institute patent litigation against any entity (including a |
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
|
||||
or a Contribution incorporated within the Work constitutes direct |
|
||||
or contributory patent infringement, then any patent licenses |
|
||||
granted to You under this License for that Work shall terminate |
|
||||
as of the date such litigation is filed. |
|
||||
|
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
|
||||
Work or Derivative Works thereof in any medium, with or without |
|
||||
modifications, and in Source or Object form, provided that You |
|
||||
meet the following conditions: |
|
||||
|
|
||||
(a) You must give any other recipients of the Work or |
|
||||
Derivative Works a copy of this License; and |
|
||||
|
|
||||
(b) You must cause any modified files to carry prominent notices |
|
||||
stating that You changed the files; and |
|
||||
|
|
||||
(c) You must retain, in the Source form of any Derivative Works |
|
||||
that You distribute, all copyright, patent, trademark, and |
|
||||
attribution notices from the Source form of the Work, |
|
||||
excluding those notices that do not pertain to any part of |
|
||||
the Derivative Works; and |
|
||||
|
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
|
||||
distribution, then any Derivative Works that You distribute must |
|
||||
include a readable copy of the attribution notices contained |
|
||||
within such NOTICE file, excluding those notices that do not |
|
||||
pertain to any part of the Derivative Works, in at least one |
|
||||
of the following places: within a NOTICE text file distributed |
|
||||
as part of the Derivative Works; within the Source form or |
|
||||
documentation, if provided along with the Derivative Works; or, |
|
||||
within a display generated by the Derivative Works, if and |
|
||||
wherever such third-party notices normally appear. The contents |
|
||||
of the NOTICE file are for informational purposes only and |
|
||||
do not modify the License. You may add Your own attribution |
|
||||
notices within Derivative Works that You distribute, alongside |
|
||||
or as an addendum to the NOTICE text from the Work, provided |
|
||||
that such additional attribution notices cannot be construed |
|
||||
as modifying the License. |
|
||||
|
|
||||
You may add Your own copyright statement to Your modifications and |
|
||||
may provide additional or different license terms and conditions |
|
||||
for use, reproduction, or distribution of Your modifications, or |
|
||||
for any such Derivative Works as a whole, provided Your use, |
|
||||
reproduction, and distribution of the Work otherwise complies with |
|
||||
the conditions stated in this License. |
|
||||
|
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
|
||||
any Contribution intentionally submitted for inclusion in the Work |
|
||||
by You to the Licensor shall be under the terms and conditions of |
|
||||
this License, without any additional terms or conditions. |
|
||||
Notwithstanding the above, nothing herein shall supersede or modify |
|
||||
the terms of any separate license agreement you may have executed |
|
||||
with Licensor regarding such Contributions. |
|
||||
|
|
||||
6. Trademarks. This License does not grant permission to use the trade |
|
||||
names, trademarks, service marks, or product names of the Licensor, |
|
||||
except as required for reasonable and customary use in describing the |
|
||||
origin of the Work and reproducing the content of the NOTICE file. |
|
||||
|
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
|
||||
agreed to in writing, Licensor provides the Work (and each |
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
|
||||
implied, including, without limitation, any warranties or conditions |
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
|
||||
appropriateness of using or redistributing the Work and assume any |
|
||||
risks associated with Your exercise of permissions under this License. |
|
||||
|
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
|
||||
whether in tort (including negligence), contract, or otherwise, |
|
||||
unless required by applicable law (such as deliberate and grossly |
|
||||
negligent acts) or agreed to in writing, shall any Contributor be |
|
||||
liable to You for damages, including any direct, indirect, special, |
|
||||
incidental, or consequential damages of any character arising as a |
|
||||
result of this License or out of the use or inability to use the |
|
||||
Work (including but not limited to damages for loss of goodwill, |
|
||||
work stoppage, computer failure or malfunction, or any and all |
|
||||
other commercial damages or losses), even if such Contributor |
|
||||
has been advised of the possibility of such damages. |
|
||||
|
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
|
||||
the Work or Derivative Works thereof, You may choose to offer, |
|
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
|
||||
or other liability obligations and/or rights consistent with this |
|
||||
License. However, in accepting such obligations, You may act only |
|
||||
on Your own behalf and on Your sole responsibility, not on behalf |
|
||||
of any other Contributor, and only if You agree to indemnify, |
|
||||
defend, and hold each Contributor harmless for any liability |
|
||||
incurred by, or claims asserted against, such Contributor by reason |
|
||||
of your accepting any such warranty or additional liability. |
|
||||
|
|
||||
END OF TERMS AND CONDITIONS |
|
||||
|
|
||||
APPENDIX: How to apply the Apache License to your work. |
|
||||
|
|
||||
To apply the Apache License to your work, attach the following |
|
||||
boilerplate notice, with the fields enclosed by brackets "[]" |
|
||||
replaced with your own identifying information. (Don't include |
|
||||
the brackets!) The text should be enclosed in the appropriate |
|
||||
comment syntax for the file format. We also recommend that a |
|
||||
file or class name and description of purpose be included on the |
|
||||
same "printed page" as the copyright notice for easier |
|
||||
identification within third-party archives. |
|
||||
|
|
||||
Copyright 2019 Huawei Technologies Co., Ltd. |
|
||||
|
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
you may not use this file except in compliance with the License. |
|
||||
You may obtain a copy of the License at |
|
||||
|
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
|
|
||||
Unless required by applicable law or agreed to in writing, software |
|
||||
distributed under the License is distributed on an "AS IS" BASIS, |
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||
See the License for the specific language governing permissions and |
|
||||
limitations under the License. |
|
||||
@ -1,39 +0,0 @@ |
|||||
OPEN SOURCE SOFTWARE NOTICE |
|
||||
|
|
||||
Please note we provide an open source software notice along with this product and/or this product firmware (in the following just “this product”). The open source software licenses are granted by the respective right holders. And the open source licenses prevail all other license information with regard to the respective open source software contained in the product, including but not limited to End User Software Licensing Agreement. This notice is provided on behalf of Huawei Technologies Co. Ltd. and any of its local subsidiaries which may have provided this product to you in your local country. |
|
||||
|
|
||||
Warranty Disclaimer |
|
||||
THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. |
|
||||
|
|
||||
Copyright Notice and License Texts |
|
||||
|
|
||||
Software: guzzle 6.3.3 |
|
||||
Copyright notice: |
|
||||
|
|
||||
Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> |
|
||||
|
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||
of this software and associated documentation files (the "Software"), to deal |
|
||||
in the Software without restriction, including without limitation the rights |
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||
copies of the Software, and to permit persons to whom the Software is |
|
||||
furnished to do so, subject to the following conditions: |
|
||||
|
|
||||
The above copyright notice and this permission notice shall be included in |
|
||||
all copies or substantial portions of the Software. |
|
||||
|
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
||||
THE SOFTWARE. |
|
||||
|
|
||||
|
|
||||
License: |
|
||||
MIT License |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -1,63 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
use Psr\Http\Message\StreamInterface; |
|
||||
use GuzzleHttp\Psr7\StreamDecoratorTrait; |
|
||||
use Obs\ObsException; |
|
||||
|
|
||||
class CheckoutStream implements StreamInterface { |
|
||||
use StreamDecoratorTrait; |
|
||||
|
|
||||
private $expectedLength; |
|
||||
private $readedCount = 0; |
|
||||
|
|
||||
public function __construct(StreamInterface $stream, $expectedLength) { |
|
||||
$this->stream = $stream; |
|
||||
$this->expectedLength = $expectedLength; |
|
||||
} |
|
||||
|
|
||||
public function getContents() { |
|
||||
$contents = $this->stream->getContents(); |
|
||||
$length = strlen($contents); |
|
||||
if ($this->expectedLength !== null && floatval($length) !== $this->expectedLength) { |
|
||||
$this -> throwObsException($this->expectedLength, $length); |
|
||||
} |
|
||||
return $contents; |
|
||||
} |
|
||||
|
|
||||
public function read($length) { |
|
||||
$string = $this->stream->read($length); |
|
||||
if ($this->expectedLength !== null) { |
|
||||
$this->readedCount += strlen($string); |
|
||||
if ($this->stream->eof()) { |
|
||||
if (floatval($this->readedCount) !== $this->expectedLength) { |
|
||||
$this -> throwObsException($this->expectedLength, $this->readedCount); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
return $string; |
|
||||
} |
|
||||
|
|
||||
public function throwObsException($expectedLength, $reaLength) { |
|
||||
$obsException = new ObsException('premature end of Content-Length delimiter message body (expected:' . $expectedLength . '; received:' . $reaLength . ')'); |
|
||||
$obsException->setExceptionType('server'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@ -1,23 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
interface ITransform { |
|
||||
public function transform($sign, $para); |
|
||||
} |
|
||||
|
|
||||
@ -1,257 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> |
|
||||
|
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||
* of this software and associated documentation files (the "Software"), to deal |
|
||||
* in the Software without restriction, including without limitation the rights |
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||
* copies of the Software, and to permit persons to whom the Software is |
|
||||
* furnished to do so, subject to the following conditions: |
|
||||
|
|
||||
* The above copyright notice and this permission notice shall be included in |
|
||||
* all copies or substantial portions of the Software. |
|
||||
|
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
||||
* THE SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
class Model implements \ArrayAccess, \IteratorAggregate, \Countable, ToArrayInterface |
|
||||
{ |
|
||||
protected $data; |
|
||||
|
|
||||
public function __construct(array $data = []) |
|
||||
{ |
|
||||
$this->data = $data; |
|
||||
} |
|
||||
|
|
||||
public function count() |
|
||||
{ |
|
||||
return count($this->data); |
|
||||
} |
|
||||
|
|
||||
public function getIterator() |
|
||||
{ |
|
||||
return new \ArrayIterator($this->data); |
|
||||
} |
|
||||
|
|
||||
public function toArray() |
|
||||
{ |
|
||||
return $this->data; |
|
||||
} |
|
||||
|
|
||||
public function clear() |
|
||||
{ |
|
||||
$this->data = []; |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function getAll(array $keys = null) |
|
||||
{ |
|
||||
return $keys ? array_intersect_key($this->data, array_flip($keys)) : $this->data; |
|
||||
} |
|
||||
|
|
||||
public function get($key) |
|
||||
{ |
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null; |
|
||||
} |
|
||||
|
|
||||
public function set($key, $value) |
|
||||
{ |
|
||||
$this->data[$key] = $value; |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function add($key, $value) |
|
||||
{ |
|
||||
if (!array_key_exists($key, $this->data)) { |
|
||||
$this->data[$key] = $value; |
|
||||
} elseif (is_array($this->data[$key])) { |
|
||||
$this->data[$key][] = $value; |
|
||||
} else { |
|
||||
$this->data[$key] = [$this->data[$key], $value]; |
|
||||
} |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function remove($key) |
|
||||
{ |
|
||||
unset($this->data[$key]); |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function getKeys() |
|
||||
{ |
|
||||
return array_keys($this->data); |
|
||||
} |
|
||||
|
|
||||
public function hasKey($key) |
|
||||
{ |
|
||||
return array_key_exists($key, $this->data); |
|
||||
} |
|
||||
|
|
||||
public function keySearch($key) |
|
||||
{ |
|
||||
foreach (array_keys($this->data) as $k) { |
|
||||
if (!strcasecmp($k, $key)) { |
|
||||
return $k; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public function hasValue($value) |
|
||||
{ |
|
||||
return array_search($value, $this->data); |
|
||||
} |
|
||||
|
|
||||
public function replace(array $data) |
|
||||
{ |
|
||||
$this->data = $data; |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function merge($data) |
|
||||
{ |
|
||||
foreach ($data as $key => $value) { |
|
||||
$this->add($key, $value); |
|
||||
} |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function overwriteWith($data) |
|
||||
{ |
|
||||
if (is_array($data)) { |
|
||||
$this->data = $data + $this->data; |
|
||||
} else { |
|
||||
foreach ($data as $key => $value) { |
|
||||
$this->data[$key] = $value; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function map(\Closure $closure, array $context = [], $static = true) |
|
||||
{ |
|
||||
$collection = $static ? new static() : new self(); |
|
||||
foreach ($this as $key => $value) { |
|
||||
$collection->add($key, $closure($key, $value, $context)); |
|
||||
} |
|
||||
|
|
||||
return $collection; |
|
||||
} |
|
||||
|
|
||||
public function filter(\Closure $closure, $static = true) |
|
||||
{ |
|
||||
$collection = ($static) ? new static() : new self(); |
|
||||
foreach ($this->data as $key => $value) { |
|
||||
if ($closure($key, $value)) { |
|
||||
$collection->add($key, $value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return $collection; |
|
||||
} |
|
||||
|
|
||||
public function offsetExists($offset) |
|
||||
{ |
|
||||
return isset($this->data[$offset]); |
|
||||
} |
|
||||
|
|
||||
public function offsetGet($offset) |
|
||||
{ |
|
||||
return isset($this->data[$offset]) ? $this->data[$offset] : null; |
|
||||
} |
|
||||
|
|
||||
public function offsetSet($offset, $value) |
|
||||
{ |
|
||||
$this->data[$offset] = $value; |
|
||||
} |
|
||||
|
|
||||
public function offsetUnset($offset) |
|
||||
{ |
|
||||
unset($this->data[$offset]); |
|
||||
} |
|
||||
|
|
||||
public function setPath($path, $value) |
|
||||
{ |
|
||||
$current =& $this->data; |
|
||||
$queue = explode('/', $path); |
|
||||
while (null !== ($key = array_shift($queue))) { |
|
||||
if (!is_array($current)) { |
|
||||
throw new \RuntimeException("Trying to setPath {$path}, but {$key} is set and is not an array"); |
|
||||
} elseif (!$queue) { |
|
||||
$current[$key] = $value; |
|
||||
} elseif (isset($current[$key])) { |
|
||||
$current =& $current[$key]; |
|
||||
} else { |
|
||||
$current[$key] = []; |
|
||||
$current =& $current[$key]; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function getPath($path, $separator = '/', $data = null) |
|
||||
{ |
|
||||
if ($data === null) { |
|
||||
$data =& $this->data; |
|
||||
} |
|
||||
|
|
||||
$path = is_array($path) ? $path : explode($separator, $path); |
|
||||
while (null !== ($part = array_shift($path))) { |
|
||||
if (!is_array($data)) { |
|
||||
return null; |
|
||||
} elseif (isset($data[$part])) { |
|
||||
$data =& $data[$part]; |
|
||||
} elseif ($part != '*') { |
|
||||
return null; |
|
||||
} else { |
|
||||
// Perform a wildcard search by diverging and merging paths |
|
||||
$result = []; |
|
||||
foreach ($data as $value) { |
|
||||
if (!$path) { |
|
||||
$result = array_merge_recursive($result, (array) $value); |
|
||||
} elseif (null !== ($test = $this->getPath($path, $separator, $value))) { |
|
||||
$result = array_merge_recursive($result, (array) $test); |
|
||||
} |
|
||||
} |
|
||||
return $result; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
public function __toString() |
|
||||
{ |
|
||||
$output = 'Debug output of '; |
|
||||
$output .= 'model'; |
|
||||
$output = str_repeat('=', strlen($output)) . "\n" . $output . "\n" . str_repeat('=', strlen($output)) . "\n\n"; |
|
||||
$output .= "Model data\n-----------\n\n"; |
|
||||
$output .= "This data can be retrieved from the model object using the get() method of the model " |
|
||||
. "(e.g. \$model->get(\$key)) or accessing the model like an associative array (e.g. \$model['key']).\n\n"; |
|
||||
$lines = array_slice(explode("\n", trim(print_r($this->toArray(), true))), 2, -1); |
|
||||
$output .= implode("\n", $lines); |
|
||||
|
|
||||
return $output . "\n"; |
|
||||
} |
|
||||
} |
|
||||
@ -1,78 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
use Obs\ObsClient; |
|
||||
|
|
||||
class ObsTransform implements ITransform { |
|
||||
private static $instance; |
|
||||
|
|
||||
private function __construct(){} |
|
||||
|
|
||||
public static function getInstance() { |
|
||||
if (!(self::$instance instanceof ObsTransform)) { |
|
||||
self::$instance = new ObsTransform(); |
|
||||
} |
|
||||
return self::$instance; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public function transform($sign, $para) { |
|
||||
if ($sign === 'aclHeader') { |
|
||||
$para = $this->transAclHeader($para); |
|
||||
} else if ($sign === 'aclUri') { |
|
||||
$para = $this->transAclGroupUri($para); |
|
||||
} else if ($sign == 'event') { |
|
||||
$para = $this->transNotificationEvent($para); |
|
||||
} else if ($sign == 'storageClass') { |
|
||||
$para = $this->transStorageClass($para); |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transAclHeader($para) { |
|
||||
if ($para === ObsClient::AclAuthenticatedRead || $para === ObsClient::AclBucketOwnerRead || |
|
||||
$para === ObsClient::AclBucketOwnerFullControl || $para === ObsClient::AclLogDeliveryWrite) { |
|
||||
$para = null; |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transAclGroupUri($para) { |
|
||||
if ($para === ObsClient::GroupAllUsers) { |
|
||||
$para = ObsClient::AllUsers; |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transNotificationEvent($para) { |
|
||||
$pos = strpos($para, 's3:'); |
|
||||
if ($pos !== false && $pos === 0) { |
|
||||
$para = substr($para, 3); |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transStorageClass($para) { |
|
||||
$search = array('STANDARD', 'STANDARD_IA', 'GLACIER'); |
|
||||
$repalce = array(ObsClient::StorageClassStandard, ObsClient::StorageClassWarm, ObsClient::StorageClassCold); |
|
||||
$para = str_replace($search, $repalce, $para); |
|
||||
return $para; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@ -1,116 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
|
|
||||
class SchemaFormatter |
|
||||
{ |
|
||||
protected static $utcTimeZone; |
|
||||
|
|
||||
public static function format($fmt, $value) |
|
||||
{ |
|
||||
if($fmt === 'date-time'){ |
|
||||
return self::formatDateTime($value); |
|
||||
} |
|
||||
|
|
||||
if($fmt === 'data-time-http'){ |
|
||||
return self::formatDateTimeHttp($value); |
|
||||
} |
|
||||
|
|
||||
if($fmt === 'data-time-middle'){ |
|
||||
return self::formatDateTimeMiddle($value); |
|
||||
} |
|
||||
|
|
||||
if($fmt === 'date'){ |
|
||||
return self::formatDate($value); |
|
||||
} |
|
||||
|
|
||||
if($fmt === 'timestamp'){ |
|
||||
return self::formatTimestamp($value); |
|
||||
} |
|
||||
|
|
||||
if($fmt === 'boolean-string'){ |
|
||||
return self::formatBooleanAsString($value); |
|
||||
} |
|
||||
|
|
||||
return $value; |
|
||||
} |
|
||||
|
|
||||
public static function formatDateTimeMiddle($dateTime) |
|
||||
{ |
|
||||
if (is_string($dateTime)) { |
|
||||
$dateTime = new \DateTime($dateTime); |
|
||||
} |
|
||||
|
|
||||
if ($dateTime instanceof \DateTime) { |
|
||||
return $dateTime -> format('Y-m-d\T00:00:00\Z'); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
public static function formatDateTime($value) |
|
||||
{ |
|
||||
return self::dateFormatter($value, 'Y-m-d\TH:i:s\Z'); |
|
||||
} |
|
||||
|
|
||||
public static function formatDateTimeHttp($value) |
|
||||
{ |
|
||||
return self::dateFormatter($value, 'D, d M Y H:i:s \G\M\T'); |
|
||||
} |
|
||||
|
|
||||
public static function formatDate($value) |
|
||||
{ |
|
||||
return self::dateFormatter($value, 'Y-m-d'); |
|
||||
} |
|
||||
|
|
||||
public static function formatTime($value) |
|
||||
{ |
|
||||
return self::dateFormatter($value, 'H:i:s'); |
|
||||
} |
|
||||
|
|
||||
public static function formatBooleanAsString($value) |
|
||||
{ |
|
||||
return filter_var($value, FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'; |
|
||||
} |
|
||||
|
|
||||
public static function formatTimestamp($value) |
|
||||
{ |
|
||||
return (int) self::dateFormatter($value, 'U'); |
|
||||
} |
|
||||
|
|
||||
private static function dateFormatter($dt, $fmt) |
|
||||
{ |
|
||||
if (is_numeric($dt)) { |
|
||||
return gmdate($fmt, (int) $dt); |
|
||||
} |
|
||||
|
|
||||
if (is_string($dt)) { |
|
||||
$dt = new \DateTime($dt); |
|
||||
} |
|
||||
|
|
||||
if ($dt instanceof \DateTime) { |
|
||||
if (!self::$utcTimeZone) { |
|
||||
self::$utcTimeZone = new \DateTimeZone('UTC'); |
|
||||
} |
|
||||
|
|
||||
return $dt->setTimezone(self::$utcTimeZone)->format($fmt); |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
} |
|
||||
@ -1,430 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> |
|
||||
|
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||
* of this software and associated documentation files (the "Software"), to deal |
|
||||
* in the Software without restriction, including without limitation the rights |
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||
* copies of the Software, and to permit persons to whom the Software is |
|
||||
* furnished to do so, subject to the following conditions: |
|
||||
|
|
||||
* The above copyright notice and this permission notice shall be included in |
|
||||
* all copies or substantial portions of the Software. |
|
||||
|
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
||||
* THE SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
use GuzzleHttp\Psr7; |
|
||||
use GuzzleHttp\Psr7\LazyOpenStream; |
|
||||
use Psr\Http\Message\RequestInterface; |
|
||||
use GuzzleHttp\Handler\CurlFactoryInterface; |
|
||||
use GuzzleHttp\Handler\EasyHandle; |
|
||||
|
|
||||
class SdkCurlFactory implements CurlFactoryInterface |
|
||||
{ |
|
||||
private $handles = []; |
|
||||
|
|
||||
private $maxHandles; |
|
||||
|
|
||||
public function __construct($maxHandles) |
|
||||
{ |
|
||||
$this->maxHandles = $maxHandles; |
|
||||
} |
|
||||
|
|
||||
public function create(RequestInterface $request, array $options): EasyHandle |
|
||||
{ |
|
||||
if (isset($options['curl']['body_as_string'])) { |
|
||||
$options['_body_as_string'] = $options['curl']['body_as_string']; |
|
||||
unset($options['curl']['body_as_string']); |
|
||||
} |
|
||||
|
|
||||
$easy = new EasyHandle; |
|
||||
$easy->request = $request; |
|
||||
$easy->options = $options; |
|
||||
$conf = $this->getDefaultConf($easy); |
|
||||
$this->applyMethod($easy, $conf); |
|
||||
$this->applyHandlerOptions($easy, $conf); |
|
||||
$this->applyHeaders($easy, $conf); |
|
||||
|
|
||||
|
|
||||
unset($conf['_headers']); |
|
||||
|
|
||||
if (isset($options['curl'])) { |
|
||||
$conf = array_replace($conf, $options['curl']); |
|
||||
} |
|
||||
|
|
||||
$conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); |
|
||||
if($this->handles){ |
|
||||
$easy->handle = array_pop($this->handles); |
|
||||
}else{ |
|
||||
$easy->handle = curl_init(); |
|
||||
} |
|
||||
curl_setopt_array($easy->handle, $conf); |
|
||||
|
|
||||
return $easy; |
|
||||
} |
|
||||
|
|
||||
public function close() |
|
||||
{ |
|
||||
if($this->handles){ |
|
||||
foreach ($this->handles as $handle){ |
|
||||
curl_close($handle); |
|
||||
} |
|
||||
unset($this->handles); |
|
||||
$this->handles = []; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public function release(EasyHandle $easy): void |
|
||||
{ |
|
||||
$resource = $easy->handle; |
|
||||
unset($easy->handle); |
|
||||
|
|
||||
if (count($this->handles) >= $this->maxHandles) { |
|
||||
curl_close($resource); |
|
||||
} else { |
|
||||
curl_setopt($resource, CURLOPT_HEADERFUNCTION, null); |
|
||||
curl_setopt($resource, CURLOPT_READFUNCTION, null); |
|
||||
curl_setopt($resource, CURLOPT_WRITEFUNCTION, null); |
|
||||
curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null); |
|
||||
curl_reset($resource); |
|
||||
$this->handles[] = $resource; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function getDefaultConf(EasyHandle $easy) |
|
||||
{ |
|
||||
$conf = [ |
|
||||
'_headers' => $easy->request->getHeaders(), |
|
||||
CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), |
|
||||
CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), |
|
||||
CURLOPT_RETURNTRANSFER => false, |
|
||||
CURLOPT_HEADER => false, |
|
||||
CURLOPT_CONNECTTIMEOUT => 150, |
|
||||
]; |
|
||||
|
|
||||
if (defined('CURLOPT_PROTOCOLS')) { |
|
||||
$conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS; |
|
||||
} |
|
||||
|
|
||||
$version = $easy->request->getProtocolVersion(); |
|
||||
if ($version == 1.1) { |
|
||||
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; |
|
||||
} elseif ($version == 2.0) { |
|
||||
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0; |
|
||||
} else { |
|
||||
$conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; |
|
||||
} |
|
||||
|
|
||||
return $conf; |
|
||||
} |
|
||||
|
|
||||
private function applyMethod(EasyHandle $easy, array &$conf) |
|
||||
{ |
|
||||
$body = $easy->request->getBody(); |
|
||||
$size = $body->getSize(); |
|
||||
|
|
||||
if ($size === null || $size > 0) { |
|
||||
$this->applyBody($easy->request, $easy->options, $conf); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
$method = $easy->request->getMethod(); |
|
||||
if ($method === 'PUT' || $method === 'POST') { |
|
||||
if (!$easy->request->hasHeader('Content-Length')) { |
|
||||
$conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; |
|
||||
} |
|
||||
} elseif ($method === 'HEAD') { |
|
||||
$conf[CURLOPT_NOBODY] = true; |
|
||||
unset( |
|
||||
$conf[CURLOPT_WRITEFUNCTION], |
|
||||
$conf[CURLOPT_READFUNCTION], |
|
||||
$conf[CURLOPT_FILE], |
|
||||
$conf[CURLOPT_INFILE] |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function applyBody(RequestInterface $request, array $options, array &$conf) |
|
||||
{ |
|
||||
$size = $request->hasHeader('Content-Length') |
|
||||
? (int) $request->getHeaderLine('Content-Length') |
|
||||
: $request->getBody()->getSize(); |
|
||||
|
|
||||
if($request->getBody()->getSize() === $size && $request -> getBody() ->tell() <= 0){ |
|
||||
if (($size !== null && $size < 1000000) || |
|
||||
!empty($options['_body_as_string']) |
|
||||
) { |
|
||||
$conf[CURLOPT_POSTFIELDS] = (string) $request->getBody(); |
|
||||
$this->removeHeader('Content-Length', $conf); |
|
||||
$this->removeHeader('Transfer-Encoding', $conf); |
|
||||
} else { |
|
||||
$conf[CURLOPT_UPLOAD] = true; |
|
||||
if ($size !== null) { |
|
||||
$conf[CURLOPT_INFILESIZE] = $size; |
|
||||
$this->removeHeader('Content-Length', $conf); |
|
||||
} |
|
||||
$body = $request->getBody(); |
|
||||
if ($body->isSeekable()) { |
|
||||
$body->rewind(); |
|
||||
} |
|
||||
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) { |
|
||||
return $body->read($length); |
|
||||
}; |
|
||||
} |
|
||||
}else{ |
|
||||
$body = $request->getBody(); |
|
||||
$conf[CURLOPT_UPLOAD] = true; |
|
||||
$conf[CURLOPT_INFILESIZE] = $size; |
|
||||
$readCount = 0; |
|
||||
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body, $readCount, $size) { |
|
||||
if($readCount >= $size){ |
|
||||
$body -> close(); |
|
||||
return ''; |
|
||||
} |
|
||||
$readCountOnce = $length <= $size ? $length : $size; |
|
||||
$readCount += $readCountOnce; |
|
||||
return $body->read($readCountOnce); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
if (!$request->hasHeader('Expect')) { |
|
||||
$conf[CURLOPT_HTTPHEADER][] = 'Expect:'; |
|
||||
} |
|
||||
|
|
||||
if (!$request->hasHeader('Content-Type')) { |
|
||||
$conf[CURLOPT_HTTPHEADER][] = 'Content-Type:'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function applyHeaders(EasyHandle $easy, array &$conf) |
|
||||
{ |
|
||||
foreach ($conf['_headers'] as $name => $values) { |
|
||||
foreach ($values as $value) { |
|
||||
$conf[CURLOPT_HTTPHEADER][] = "$name: $value"; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Remove the Accept header if one was not set |
|
||||
if (!$easy->request->hasHeader('Accept')) { |
|
||||
$conf[CURLOPT_HTTPHEADER][] = 'Accept:'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function removeHeader($name, array &$options) |
|
||||
{ |
|
||||
foreach (array_keys($options['_headers']) as $key) { |
|
||||
if (!strcasecmp($key, $name)) { |
|
||||
unset($options['_headers'][$key]); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function applyHandlerOptions(EasyHandle $easy, array &$conf) |
|
||||
{ |
|
||||
$options = $easy->options; |
|
||||
if (isset($options['verify'])) { |
|
||||
$conf[CURLOPT_SSL_VERIFYHOST] = 0; |
|
||||
if ($options['verify'] === false) { |
|
||||
unset($conf[CURLOPT_CAINFO]); |
|
||||
$conf[CURLOPT_SSL_VERIFYPEER] = false; |
|
||||
} else { |
|
||||
$conf[CURLOPT_SSL_VERIFYPEER] = true; |
|
||||
if (is_string($options['verify'])) { |
|
||||
if (!file_exists($options['verify'])) { |
|
||||
throw new \InvalidArgumentException( |
|
||||
"SSL CA bundle not found: {$options['verify']}" |
|
||||
); |
|
||||
} |
|
||||
if (is_dir($options['verify']) || |
|
||||
(is_link($options['verify']) && is_dir(readlink($options['verify'])))) { |
|
||||
$conf[CURLOPT_CAPATH] = $options['verify']; |
|
||||
} else { |
|
||||
$conf[CURLOPT_CAINFO] = $options['verify']; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (!empty($options['decode_content'])) { |
|
||||
$accept = $easy->request->getHeaderLine('Accept-Encoding'); |
|
||||
if ($accept) { |
|
||||
$conf[CURLOPT_ENCODING] = $accept; |
|
||||
} else { |
|
||||
$conf[CURLOPT_ENCODING] = ''; |
|
||||
$conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (isset($options['sink'])) { |
|
||||
$sink = $options['sink']; |
|
||||
if (!is_string($sink)) { |
|
||||
try { |
|
||||
$sink = Psr7\stream_for($sink); |
|
||||
} catch (\Throwable $e) { |
|
||||
$sink = Psr7\Utils::streamFor($sink); |
|
||||
} |
|
||||
} elseif (!is_dir(dirname($sink))) { |
|
||||
throw new \RuntimeException(sprintf( |
|
||||
'Directory %s does not exist for sink value of %s', |
|
||||
dirname($sink), |
|
||||
$sink |
|
||||
)); |
|
||||
} else { |
|
||||
$sink = new LazyOpenStream($sink, 'w+'); |
|
||||
} |
|
||||
$easy->sink = $sink; |
|
||||
$conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) { |
|
||||
return $sink->write($write); |
|
||||
}; |
|
||||
} else { |
|
||||
$conf[CURLOPT_FILE] = fopen('php://temp', 'w+'); |
|
||||
try { |
|
||||
$easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]); |
|
||||
} catch (\Throwable $e) { |
|
||||
$easy->sink = Psr7\Utils::streamFor($conf[CURLOPT_FILE]); |
|
||||
} |
|
||||
} |
|
||||
$timeoutRequiresNoSignal = false; |
|
||||
if (isset($options['timeout'])) { |
|
||||
$timeoutRequiresNoSignal |= $options['timeout'] < 1; |
|
||||
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; |
|
||||
} |
|
||||
|
|
||||
if (isset($options['force_ip_resolve'])) { |
|
||||
if ('v4' === $options['force_ip_resolve']) { |
|
||||
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4; |
|
||||
} else if ('v6' === $options['force_ip_resolve']) { |
|
||||
$conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (isset($options['connect_timeout'])) { |
|
||||
$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; |
|
||||
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; |
|
||||
} |
|
||||
|
|
||||
if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { |
|
||||
$conf[CURLOPT_NOSIGNAL] = true; |
|
||||
} |
|
||||
|
|
||||
if (isset($options['proxy'])) { |
|
||||
if (!is_array($options['proxy'])) { |
|
||||
$conf[CURLOPT_PROXY] = $options['proxy']; |
|
||||
} else { |
|
||||
$scheme = $easy->request->getUri()->getScheme(); |
|
||||
if (isset($options['proxy'][$scheme])) { |
|
||||
$host = $easy->request->getUri()->getHost(); |
|
||||
if (!isset($options['proxy']['no']) || |
|
||||
!\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no']) |
|
||||
) { |
|
||||
$conf[CURLOPT_PROXY] = $options['proxy'][$scheme]; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (isset($options['cert'])) { |
|
||||
$cert = $options['cert']; |
|
||||
if (is_array($cert)) { |
|
||||
$conf[CURLOPT_SSLCERTPASSWD] = $cert[1]; |
|
||||
$cert = $cert[0]; |
|
||||
} |
|
||||
if (!file_exists($cert)) { |
|
||||
throw new \InvalidArgumentException( |
|
||||
"SSL certificate not found: {$cert}" |
|
||||
); |
|
||||
} |
|
||||
$conf[CURLOPT_SSLCERT] = $cert; |
|
||||
} |
|
||||
|
|
||||
if (isset($options['ssl_key'])) { |
|
||||
$sslKey = $options['ssl_key']; |
|
||||
if (is_array($sslKey)) { |
|
||||
$conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1]; |
|
||||
$sslKey = $sslKey[0]; |
|
||||
} |
|
||||
if (!file_exists($sslKey)) { |
|
||||
throw new \InvalidArgumentException( |
|
||||
"SSL private key not found: {$sslKey}" |
|
||||
); |
|
||||
} |
|
||||
$conf[CURLOPT_SSLKEY] = $sslKey; |
|
||||
} |
|
||||
|
|
||||
if (isset($options['progress'])) { |
|
||||
$progress = $options['progress']; |
|
||||
if (!is_callable($progress)) { |
|
||||
throw new \InvalidArgumentException( |
|
||||
'progress client option must be callable' |
|
||||
); |
|
||||
} |
|
||||
$conf[CURLOPT_NOPROGRESS] = false; |
|
||||
$conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) { |
|
||||
$args = func_get_args(); |
|
||||
if (is_resource($args[0])) { |
|
||||
array_shift($args); |
|
||||
} |
|
||||
call_user_func_array($progress, $args); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
if (!empty($options['debug'])) { |
|
||||
$conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']); |
|
||||
$conf[CURLOPT_VERBOSE] = true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
private function createHeaderFn(EasyHandle $easy) |
|
||||
{ |
|
||||
if (isset($easy->options['on_headers'])) { |
|
||||
$onHeaders = $easy->options['on_headers']; |
|
||||
|
|
||||
if (!is_callable($onHeaders)) { |
|
||||
throw new \InvalidArgumentException('on_headers must be callable'); |
|
||||
} |
|
||||
} else { |
|
||||
$onHeaders = null; |
|
||||
} |
|
||||
|
|
||||
return function ($ch, $h) use ( |
|
||||
$onHeaders, |
|
||||
$easy, |
|
||||
&$startingResponse |
|
||||
) { |
|
||||
$value = trim($h); |
|
||||
if ($value === '') { |
|
||||
$startingResponse = true; |
|
||||
$easy->createResponse(); |
|
||||
if ($onHeaders !== null) { |
|
||||
try { |
|
||||
$onHeaders($easy->response); |
|
||||
} catch (\Exception $e) { |
|
||||
$easy->onHeadersException = $e; |
|
||||
return -1; |
|
||||
} |
|
||||
} |
|
||||
} elseif ($startingResponse) { |
|
||||
$startingResponse = false; |
|
||||
$easy->headers = [$value]; |
|
||||
} else { |
|
||||
$easy->headers[] = $value; |
|
||||
} |
|
||||
return strlen($h); |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
@ -1,519 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> |
|
||||
|
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||
* of this software and associated documentation files (the "Software"), to deal |
|
||||
* in the Software without restriction, including without limitation the rights |
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||
* copies of the Software, and to permit persons to whom the Software is |
|
||||
* furnished to do so, subject to the following conditions: |
|
||||
|
|
||||
* The above copyright notice and this permission notice shall be included in |
|
||||
* all copies or substantial portions of the Software. |
|
||||
|
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
||||
* THE SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
use GuzzleHttp\Exception\RequestException; |
|
||||
use GuzzleHttp\Exception\ConnectException; |
|
||||
use GuzzleHttp\Promise\FulfilledPromise; |
|
||||
use GuzzleHttp\Promise\PromiseInterface; |
|
||||
use GuzzleHttp\Psr7; |
|
||||
use GuzzleHttp\TransferStats; |
|
||||
use Psr\Http\Message\RequestInterface; |
|
||||
use Psr\Http\Message\ResponseInterface; |
|
||||
use Psr\Http\Message\StreamInterface; |
|
||||
|
|
||||
class SdkStreamHandler |
|
||||
{ |
|
||||
private $lastHeaders = []; |
|
||||
|
|
||||
public function __invoke(RequestInterface $request, array $options) |
|
||||
{ |
|
||||
if (isset($options['delay'])) { |
|
||||
usleep($options['delay'] * 1000); |
|
||||
} |
|
||||
|
|
||||
$startTime = isset($options['on_stats']) ? microtime(true) : null; |
|
||||
|
|
||||
try { |
|
||||
$request = $request->withoutHeader('Expect'); |
|
||||
|
|
||||
if (0 === $request->getBody()->getSize()) { |
|
||||
$request = $request->withHeader('Content-Length', 0); |
|
||||
} |
|
||||
|
|
||||
return $this->createResponse( |
|
||||
$request, |
|
||||
$options, |
|
||||
$this->createStream($request, $options), |
|
||||
$startTime |
|
||||
); |
|
||||
} catch (\InvalidArgumentException $e) { |
|
||||
throw $e; |
|
||||
} catch (\Exception $e) { |
|
||||
$message = $e->getMessage(); |
|
||||
if (strpos($message, 'getaddrinfo') |
|
||||
|| strpos($message, 'Connection refused') |
|
||||
|| strpos($message, "couldn't connect to host") |
|
||||
) { |
|
||||
$e = new ConnectException($e->getMessage(), $request, $e); |
|
||||
} |
|
||||
$e = RequestException::wrapException($request, $e); |
|
||||
$this->invokeStats($options, $request, $startTime, null, $e); |
|
||||
|
|
||||
return \GuzzleHttp\Promise\rejection_for($e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function invokeStats( |
|
||||
array $options, |
|
||||
RequestInterface $request, |
|
||||
$startTime, |
|
||||
ResponseInterface $response = null, |
|
||||
$error = null |
|
||||
) { |
|
||||
if (isset($options['on_stats'])) { |
|
||||
$stats = new TransferStats( |
|
||||
$request, |
|
||||
$response, |
|
||||
microtime(true) - $startTime, |
|
||||
$error, |
|
||||
[] |
|
||||
); |
|
||||
call_user_func($options['on_stats'], $stats); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function createResponse( |
|
||||
RequestInterface $request, |
|
||||
array $options, |
|
||||
$stream, |
|
||||
$startTime |
|
||||
) { |
|
||||
$hdrs = $this->lastHeaders; |
|
||||
$this->lastHeaders = []; |
|
||||
$parts = explode(' ', array_shift($hdrs), 3); |
|
||||
$ver = explode('/', $parts[0])[1]; |
|
||||
$status = $parts[1]; |
|
||||
$reason = isset($parts[2]) ? $parts[2] : null; |
|
||||
$headers = \GuzzleHttp\headers_from_lines($hdrs); |
|
||||
list ($stream, $headers) = $this->checkDecode($options, $headers, $stream); |
|
||||
try { |
|
||||
$stream = Psr7\stream_for($stream); |
|
||||
} catch (\Throwable $e) { |
|
||||
$stream = Psr7\Utils::streamFor($stream); |
|
||||
} |
|
||||
$sink = $stream; |
|
||||
|
|
||||
if (strcasecmp('HEAD', $request->getMethod())) { |
|
||||
$sink = $this->createSink($stream, $options); |
|
||||
} |
|
||||
|
|
||||
$response = new Psr7\Response($status, $headers, $sink, $ver, $reason); |
|
||||
|
|
||||
if (isset($options['on_headers'])) { |
|
||||
try { |
|
||||
$options['on_headers']($response); |
|
||||
} catch (\Exception $e) { |
|
||||
$msg = 'An error was encountered during the on_headers event'; |
|
||||
$ex = new RequestException($msg, $request, $response, $e); |
|
||||
return \GuzzleHttp\Promise\rejection_for($ex); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if ($sink !== $stream) { |
|
||||
$this->drain( |
|
||||
$stream, |
|
||||
$sink, |
|
||||
$response->getHeaderLine('Content-Length') |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
$this->invokeStats($options, $request, $startTime, $response, null); |
|
||||
|
|
||||
return new FulfilledPromise($response); |
|
||||
} |
|
||||
|
|
||||
private function createSink(StreamInterface $stream, array $options) |
|
||||
{ |
|
||||
if (!empty($options['stream'])) { |
|
||||
return $stream; |
|
||||
} |
|
||||
|
|
||||
$sink = isset($options['sink']) |
|
||||
? $options['sink'] |
|
||||
: fopen('php://temp', 'r+'); |
|
||||
|
|
||||
if (is_string($sink)) { |
|
||||
return new Psr7\LazyOpenStream($sink, 'w+'); |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
return Psr7\stream_for($sink); |
|
||||
} catch (\Throwable $e) { |
|
||||
return Psr7\Utils::streamFor($sink); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function checkDecode(array $options, array $headers, $stream) |
|
||||
{ |
|
||||
if (!empty($options['decode_content'])) { |
|
||||
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers); |
|
||||
if (isset($normalizedKeys['content-encoding'])) { |
|
||||
$encoding = $headers[$normalizedKeys['content-encoding']]; |
|
||||
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { |
|
||||
try { |
|
||||
$stream = new Psr7\InflateStream( |
|
||||
Psr7\stream_for($stream) |
|
||||
); |
|
||||
} catch (\Throwable $th) { |
|
||||
$stream = new Psr7\InflateStream( |
|
||||
Psr7\Utils::streamFor($stream) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
$headers['x-encoded-content-encoding'] |
|
||||
= $headers[$normalizedKeys['content-encoding']]; |
|
||||
unset($headers[$normalizedKeys['content-encoding']]); |
|
||||
if (isset($normalizedKeys['content-length'])) { |
|
||||
$headers['x-encoded-content-length'] |
|
||||
= $headers[$normalizedKeys['content-length']]; |
|
||||
|
|
||||
$length = (int) $stream->getSize(); |
|
||||
if ($length === 0) { |
|
||||
unset($headers[$normalizedKeys['content-length']]); |
|
||||
} else { |
|
||||
$headers[$normalizedKeys['content-length']] = [$length]; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return [$stream, $headers]; |
|
||||
} |
|
||||
|
|
||||
private function drain( |
|
||||
StreamInterface $source, |
|
||||
StreamInterface $sink, |
|
||||
$contentLength |
|
||||
) { |
|
||||
Psr7\copy_to_stream( |
|
||||
$source, |
|
||||
$sink, |
|
||||
(strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1 |
|
||||
); |
|
||||
|
|
||||
$sink->seek(0); |
|
||||
$source->close(); |
|
||||
|
|
||||
return $sink; |
|
||||
} |
|
||||
|
|
||||
private function createResource(callable $callback) |
|
||||
{ |
|
||||
$errors = null; |
|
||||
set_error_handler(function ($_, $msg, $file, $line) use (&$errors) { |
|
||||
$errors[] = [ |
|
||||
'message' => $msg, |
|
||||
'file' => $file, |
|
||||
'line' => $line |
|
||||
]; |
|
||||
return true; |
|
||||
}); |
|
||||
|
|
||||
$resource = $callback(); |
|
||||
restore_error_handler(); |
|
||||
|
|
||||
if (!$resource) { |
|
||||
$message = 'Error creating resource: '; |
|
||||
foreach ($errors as $err) { |
|
||||
foreach ($err as $key => $value) { |
|
||||
$message .= "[$key] $value" . PHP_EOL; |
|
||||
} |
|
||||
} |
|
||||
throw new \RuntimeException(trim($message)); |
|
||||
} |
|
||||
|
|
||||
return $resource; |
|
||||
} |
|
||||
|
|
||||
private function createStream(RequestInterface $request, array $options) |
|
||||
{ |
|
||||
static $methods; |
|
||||
if (!$methods) { |
|
||||
$methods = array_flip(get_class_methods(__CLASS__)); |
|
||||
} |
|
||||
|
|
||||
if ($request->getProtocolVersion() == '1.1' |
|
||||
&& !$request->hasHeader('Connection') |
|
||||
) { |
|
||||
$request = $request->withHeader('Connection', 'close'); |
|
||||
} |
|
||||
|
|
||||
if (!isset($options['verify'])) { |
|
||||
$options['verify'] = true; |
|
||||
} |
|
||||
|
|
||||
$params = []; |
|
||||
$context = $this->getDefaultContext($request, $options); |
|
||||
|
|
||||
if (isset($options['on_headers']) && !is_callable($options['on_headers'])) { |
|
||||
throw new \InvalidArgumentException('on_headers must be callable'); |
|
||||
} |
|
||||
|
|
||||
if (!empty($options)) { |
|
||||
foreach ($options as $key => $value) { |
|
||||
$method = "add_{$key}"; |
|
||||
if (isset($methods[$method])) { |
|
||||
$this->{$method}($request, $context, $value, $params); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (isset($options['stream_context'])) { |
|
||||
if (!is_array($options['stream_context'])) { |
|
||||
throw new \InvalidArgumentException('stream_context must be an array'); |
|
||||
} |
|
||||
$context = array_replace_recursive( |
|
||||
$context, |
|
||||
$options['stream_context'] |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
if (isset($options['auth']) |
|
||||
&& is_array($options['auth']) |
|
||||
&& isset($options['auth'][2]) |
|
||||
&& 'ntlm' == $options['auth'][2] |
|
||||
) { |
|
||||
|
|
||||
throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); |
|
||||
} |
|
||||
|
|
||||
$uri = $this->resolveHost($request, $options); |
|
||||
|
|
||||
$context = $this->createResource( |
|
||||
function () use ($context, $params) { |
|
||||
return stream_context_create($context, $params); |
|
||||
} |
|
||||
); |
|
||||
|
|
||||
return $this->createResource( |
|
||||
function () use ($uri, &$http_response_header, $context, $options) { |
|
||||
$resource = fopen((string) $uri, 'r', null, $context); |
|
||||
$this->lastHeaders = $http_response_header; |
|
||||
|
|
||||
if (isset($options['read_timeout'])) { |
|
||||
$readTimeout = $options['read_timeout']; |
|
||||
$sec = (int) $readTimeout; |
|
||||
$usec = ($readTimeout - $sec) * 100000; |
|
||||
stream_set_timeout($resource, $sec, $usec); |
|
||||
} |
|
||||
|
|
||||
return $resource; |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
private function resolveHost(RequestInterface $request, array $options) |
|
||||
{ |
|
||||
$uri = $request->getUri(); |
|
||||
|
|
||||
if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) { |
|
||||
if ('v4' === $options['force_ip_resolve']) { |
|
||||
$records = dns_get_record($uri->getHost(), DNS_A); |
|
||||
if (!isset($records[0]['ip'])) { |
|
||||
throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); |
|
||||
} |
|
||||
$uri = $uri->withHost($records[0]['ip']); |
|
||||
} elseif ('v6' === $options['force_ip_resolve']) { |
|
||||
$records = dns_get_record($uri->getHost(), DNS_AAAA); |
|
||||
if (!isset($records[0]['ipv6'])) { |
|
||||
throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); |
|
||||
} |
|
||||
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']'); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return $uri; |
|
||||
} |
|
||||
|
|
||||
private function getDefaultContext(RequestInterface $request) |
|
||||
{ |
|
||||
$headers = ''; |
|
||||
foreach ($request->getHeaders() as $name => $value) { |
|
||||
foreach ($value as $val) { |
|
||||
$headers .= "$name: $val\r\n"; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$context = [ |
|
||||
'http' => [ |
|
||||
'method' => $request->getMethod(), |
|
||||
'header' => $headers, |
|
||||
'protocol_version' => $request->getProtocolVersion(), |
|
||||
'ignore_errors' => true, |
|
||||
'follow_location' => 0, |
|
||||
], |
|
||||
]; |
|
||||
|
|
||||
$body = (string) $request->getBody(); |
|
||||
|
|
||||
if (!empty($body)) { |
|
||||
$context['http']['content'] = $body; |
|
||||
if (!$request->hasHeader('Content-Type')) { |
|
||||
$context['http']['header'] .= "Content-Type:\r\n"; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$context['http']['header'] = rtrim($context['http']['header']); |
|
||||
|
|
||||
return $context; |
|
||||
} |
|
||||
|
|
||||
private function add_proxy(RequestInterface $request, &$options, $value, &$params) |
|
||||
{ |
|
||||
if (!is_array($value)) { |
|
||||
$options['http']['proxy'] = $value; |
|
||||
} else { |
|
||||
$scheme = $request->getUri()->getScheme(); |
|
||||
if (isset($value[$scheme])) { |
|
||||
if (!isset($value['no']) |
|
||||
|| !\GuzzleHttp\is_host_in_noproxy( |
|
||||
$request->getUri()->getHost(), |
|
||||
$value['no'] |
|
||||
) |
|
||||
) { |
|
||||
$options['http']['proxy'] = $value[$scheme]; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function add_timeout(RequestInterface $request, &$options, $value, &$params) |
|
||||
{ |
|
||||
if ($value > 0) { |
|
||||
$options['http']['timeout'] = $value; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function add_verify(RequestInterface $request, &$options, $value, &$params) |
|
||||
{ |
|
||||
if ($value === true) { |
|
||||
if (PHP_VERSION_ID < 50600) { |
|
||||
$options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle(); |
|
||||
} |
|
||||
} elseif (is_string($value)) { |
|
||||
$options['ssl']['cafile'] = $value; |
|
||||
if (!file_exists($value)) { |
|
||||
throw new \RuntimeException("SSL CA bundle not found: $value"); |
|
||||
} |
|
||||
} elseif ($value === false) { |
|
||||
$options['ssl']['verify_peer'] = false; |
|
||||
$options['ssl']['verify_peer_name'] = false; |
|
||||
return; |
|
||||
} else { |
|
||||
throw new \InvalidArgumentException('Invalid verify request option'); |
|
||||
} |
|
||||
|
|
||||
$options['ssl']['verify_peer'] = true; |
|
||||
$options['ssl']['verify_peer_name'] = true; |
|
||||
$options['ssl']['allow_self_signed'] = false; |
|
||||
} |
|
||||
|
|
||||
private function add_cert(RequestInterface $request, &$options, $value, &$params) |
|
||||
{ |
|
||||
if (is_array($value)) { |
|
||||
$options['ssl']['passphrase'] = $value[1]; |
|
||||
$value = $value[0]; |
|
||||
} |
|
||||
|
|
||||
if (!file_exists($value)) { |
|
||||
throw new \RuntimeException("SSL certificate not found: {$value}"); |
|
||||
} |
|
||||
|
|
||||
$options['ssl']['local_cert'] = $value; |
|
||||
} |
|
||||
|
|
||||
private function add_progress(RequestInterface $request, &$options, $value, &$params) |
|
||||
{ |
|
||||
$this->addNotification( |
|
||||
$params, |
|
||||
function ($code, $a, $b, $c, $transferred, $total) use ($value) { |
|
||||
if ($code == STREAM_NOTIFY_PROGRESS) { |
|
||||
$value($total, $transferred, null, null); |
|
||||
} |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
private function add_debug(RequestInterface $request, &$options, $value, &$params) |
|
||||
{ |
|
||||
if ($value === false) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
static $map = [ |
|
||||
STREAM_NOTIFY_CONNECT => 'CONNECT', |
|
||||
STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', |
|
||||
STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', |
|
||||
STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', |
|
||||
STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', |
|
||||
STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', |
|
||||
STREAM_NOTIFY_PROGRESS => 'PROGRESS', |
|
||||
STREAM_NOTIFY_FAILURE => 'FAILURE', |
|
||||
STREAM_NOTIFY_COMPLETED => 'COMPLETED', |
|
||||
STREAM_NOTIFY_RESOLVE => 'RESOLVE', |
|
||||
]; |
|
||||
static $args = ['severity', 'message', 'message_code', |
|
||||
'bytes_transferred', 'bytes_max']; |
|
||||
|
|
||||
$value = \GuzzleHttp\debug_resource($value); |
|
||||
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment(''); |
|
||||
$this->addNotification( |
|
||||
$params, |
|
||||
function () use ($ident, $value, $map, $args) { |
|
||||
$passed = func_get_args(); |
|
||||
$code = array_shift($passed); |
|
||||
fprintf($value, '<%s> [%s] ', $ident, $map[$code]); |
|
||||
foreach (array_filter($passed) as $i => $v) { |
|
||||
fwrite($value, $args[$i] . ': "' . $v . '" '); |
|
||||
} |
|
||||
fwrite($value, "\n"); |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
private function addNotification(array &$params, callable $notify) |
|
||||
{ |
|
||||
if (!isset($params['notification'])) { |
|
||||
$params['notification'] = $notify; |
|
||||
} else { |
|
||||
$params['notification'] = $this->callArray([ |
|
||||
$params['notification'], |
|
||||
$notify |
|
||||
]); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function callArray(array $functions) |
|
||||
{ |
|
||||
return function () use ($functions) { |
|
||||
$args = func_get_args(); |
|
||||
foreach ($functions as $fn) { |
|
||||
call_user_func_array($fn, $args); |
|
||||
} |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
interface ToArrayInterface |
|
||||
{ |
|
||||
public function toArray(); |
|
||||
} |
|
||||
@ -1,83 +0,0 @@ |
|||||
<?php |
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Common; |
|
||||
|
|
||||
use Obs\ObsClient; |
|
||||
use Obs\Internal\Resource\V2Constants; |
|
||||
|
|
||||
class V2Transform implements ITransform{ |
|
||||
private static $instance; |
|
||||
|
|
||||
private function __construct(){} |
|
||||
|
|
||||
public static function getInstance() { |
|
||||
if (!(self::$instance instanceof V2Transform)) { |
|
||||
self::$instance = new V2Transform(); |
|
||||
} |
|
||||
return self::$instance; |
|
||||
} |
|
||||
|
|
||||
public function transform($sign, $para) { |
|
||||
if ($sign === 'storageClass') { |
|
||||
$para = $this->transStorageClass($para); |
|
||||
} else if ($sign === 'aclHeader') { |
|
||||
$para = $this->transAclHeader($para); |
|
||||
} else if ($sign === 'aclUri') { |
|
||||
$para = $this->transAclGroupUri($para); |
|
||||
} else if ($sign == 'event') { |
|
||||
$para = $this->transNotificationEvent($para); |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transStorageClass($para) { |
|
||||
$search = array(ObsClient::StorageClassStandard, ObsClient::StorageClassWarm, ObsClient::StorageClassCold); |
|
||||
$repalce = array('STANDARD', 'STANDARD_IA', 'GLACIER'); |
|
||||
$para = str_replace($search, $repalce, $para); |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transAclHeader($para) { |
|
||||
if ($para === ObsClient::AclPublicReadDelivered || $para === ObsClient::AclPublicReadWriteDelivered) { |
|
||||
$para = null; |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transAclGroupUri($para) { |
|
||||
if ($para === ObsClient::GroupAllUsers) { |
|
||||
$para = V2Constants::GROUP_ALL_USERS_PREFIX . $para; |
|
||||
} else if ($para === ObsClient::GroupAuthenticatedUsers) { |
|
||||
$para = V2Constants::GROUP_AUTHENTICATED_USERS_PREFIX . $para; |
|
||||
} else if ($para === ObsClient::GroupLogDelivery) { |
|
||||
$para = V2Constants::GROUP_LOG_DELIVERY_PREFIX . $para; |
|
||||
} else if ($para === ObsClient::AllUsers) { |
|
||||
$para = V2Constants::GROUP_ALL_USERS_PREFIX . ObsClient::GroupAllUsers; |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
|
|
||||
private function transNotificationEvent($para) { |
|
||||
$pos = strpos($para, 's3:'); |
|
||||
if ($pos === false || $pos !== 0) { |
|
||||
$para = 's3:' . $para; |
|
||||
} |
|
||||
return $para; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
@ -1,455 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal; |
|
||||
use GuzzleHttp\Psr7\Request; |
|
||||
use GuzzleHttp\Psr7\Response; |
|
||||
use GuzzleHttp\Exception\RequestException; |
|
||||
use Obs\ObsException; |
|
||||
use Obs\Internal\Common\Model; |
|
||||
use Obs\Internal\Resource\Constants; |
|
||||
use Obs\Log\ObsLog; |
|
||||
use Psr\Http\Message\StreamInterface; |
|
||||
use Obs\Internal\Common\CheckoutStream; |
|
||||
|
|
||||
trait GetResponseTrait |
|
||||
{ |
|
||||
|
|
||||
protected $exceptionResponseMode = true; |
|
||||
|
|
||||
protected $chunkSize = 65536; |
|
||||
|
|
||||
protected function isClientError(Response $response) |
|
||||
{ |
|
||||
return $response -> getStatusCode() >= 400 && $response -> getStatusCode() < 500; |
|
||||
} |
|
||||
|
|
||||
protected function parseXmlByType($searchPath, $key, &$value, $xml, $prefix) |
|
||||
{ |
|
||||
$type = 'string'; |
|
||||
|
|
||||
if(isset($value['sentAs'])){ |
|
||||
$key = $value['sentAs']; |
|
||||
} |
|
||||
|
|
||||
if($searchPath === null){ |
|
||||
$searchPath = '//'.$prefix.$key; |
|
||||
} |
|
||||
|
|
||||
if(isset($value['type'])){ |
|
||||
$type = $value['type']; |
|
||||
if($type === 'array'){ |
|
||||
$items = $value['items']; |
|
||||
if(isset($value['wrapper'])){ |
|
||||
$paths = explode('/', $searchPath); |
|
||||
$size = count($paths); |
|
||||
if ($size > 1) { |
|
||||
$end = $paths[$size - 1]; |
|
||||
$paths[$size - 1] = $value['wrapper']; |
|
||||
$paths[] = $end; |
|
||||
$searchPath = implode('/', $paths) .'/' . $prefix; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$array = []; |
|
||||
if(!isset($value['data']['xmlFlattened'])){ |
|
||||
$pkey = isset($items['sentAs']) ? $items['sentAs'] : $items['name']; |
|
||||
$_searchPath = $searchPath .'/' . $prefix .$pkey; |
|
||||
}else{ |
|
||||
$pkey = $key; |
|
||||
$_searchPath = $searchPath; |
|
||||
} |
|
||||
if($result = $xml -> xpath($_searchPath)){ |
|
||||
if(is_array($result)){ |
|
||||
foreach ($result as $subXml){ |
|
||||
$subXml = simplexml_load_string($subXml -> asXML()); |
|
||||
$subPrefix = $this->getXpathPrefix($subXml); |
|
||||
$array[] = $this->parseXmlByType('//'.$subPrefix. $pkey, $pkey, $items, $subXml, $subPrefix); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
return $array; |
|
||||
}else if($type === 'object'){ |
|
||||
$properties = $value['properties']; |
|
||||
$array = []; |
|
||||
foreach ($properties as $pkey => $pvalue){ |
|
||||
$name = isset($pvalue['sentAs']) ? $pvalue['sentAs'] : $pkey; |
|
||||
$array[$pkey] = $this->parseXmlByType($searchPath.'/' . $prefix .$name, $name, $pvalue, $xml, $prefix); |
|
||||
} |
|
||||
return $array; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($result = $xml -> xpath($searchPath)){ |
|
||||
if($type === 'boolean'){ |
|
||||
return strval($result[0]) !== 'false'; |
|
||||
}else if($type === 'numeric' || $type === 'float'){ |
|
||||
return floatval($result[0]); |
|
||||
}else if($type === 'int' || $type === 'integer'){ |
|
||||
return intval($result[0]); |
|
||||
}else{ |
|
||||
return strval($result[0]); |
|
||||
} |
|
||||
}else{ |
|
||||
if($type === 'boolean'){ |
|
||||
return false; |
|
||||
}else if($type === 'numeric' || $type === 'float' || $type === 'int' || $type === 'integer'){ |
|
||||
return null; |
|
||||
}else{ |
|
||||
return ''; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function isJsonResponse($response) { |
|
||||
return $response -> getHeaderLine('content-type') === 'application/json'; |
|
||||
} |
|
||||
|
|
||||
private function parseCommonHeaders($model, $response){ |
|
||||
$constants = Constants::selectConstants($this -> signature); |
|
||||
foreach($constants::COMMON_HEADERS as $key => $value){ |
|
||||
$model[$value] = $response -> getHeaderLine($key); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected function parseItems($responseParameters, $model, $response, $body) |
|
||||
{ |
|
||||
$prefix = ''; |
|
||||
|
|
||||
$this->parseCommonHeaders($model, $response); |
|
||||
|
|
||||
$closeBody = false; |
|
||||
try{ |
|
||||
foreach ($responseParameters as $key => $value){ |
|
||||
if(isset($value['location'])){ |
|
||||
$location = $value['location']; |
|
||||
if($location === 'header'){ |
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : $key; |
|
||||
$isSet = false; |
|
||||
if(isset($value['type'])){ |
|
||||
$type = $value['type']; |
|
||||
if($type === 'object'){ |
|
||||
$headers = $response -> getHeaders(); |
|
||||
$temp = []; |
|
||||
foreach ($headers as $headerName => $headerValue){ |
|
||||
if(stripos($headerName, $name) === 0){ |
|
||||
$metaKey = rawurldecode(substr($headerName, strlen($name))); |
|
||||
$temp[$metaKey] = rawurldecode($response -> getHeaderLine($headerName)); |
|
||||
} |
|
||||
} |
|
||||
$model[$key] = $temp; |
|
||||
$isSet = true; |
|
||||
}else{ |
|
||||
if($response -> hasHeader($name)){ |
|
||||
if($type === 'boolean'){ |
|
||||
$model[$key] = ($response -> getHeaderLine($name)) !== 'false'; |
|
||||
$isSet = true; |
|
||||
}else if($type === 'numeric' || $type === 'float'){ |
|
||||
$model[$key] = floatval($response -> getHeaderLine($name)); |
|
||||
$isSet = true; |
|
||||
}else if($type === 'int' || $type === 'integer'){ |
|
||||
$model[$key] = intval($response -> getHeaderLine($name)); |
|
||||
$isSet = true; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
if(!$isSet){ |
|
||||
$model[$key] = rawurldecode($response -> getHeaderLine($name)); |
|
||||
} |
|
||||
}else if($location === 'xml' && $body !== null){ |
|
||||
if(!isset($xml) && ($xml = simplexml_load_string($body -> getContents()))){ |
|
||||
$prefix = $this ->getXpathPrefix($xml); |
|
||||
} |
|
||||
$closeBody = true; |
|
||||
$model[$key] = $this -> parseXmlByType(null, $key,$value, $xml, $prefix); |
|
||||
}else if($location === 'body' && $body !== null){ |
|
||||
if(isset($value['type']) && $value['type'] === 'stream'){ |
|
||||
$model[$key] = $body; |
|
||||
}else if (isset($value['type']) && $value['type'] === 'json') { |
|
||||
$jsonBody = trim($body -> getContents()); |
|
||||
if ($jsonBody && ($data = json_decode($jsonBody, true))) { |
|
||||
if (is_array($data)) { |
|
||||
$model[$key] = $data; |
|
||||
} elseif (strlen($data)) { |
|
||||
ObsLog::commonLog(ERROR, "response body %s, and jsonToArray data is %s",$body, $data); |
|
||||
} |
|
||||
} |
|
||||
$closeBody = true; |
|
||||
} else { |
|
||||
$model[$key] = $body -> getContents(); |
|
||||
$closeBody = true; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}finally { |
|
||||
if($closeBody && $body !== null){ |
|
||||
$body -> close(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function writeFile($filePath, StreamInterface &$body, $contentLength) |
|
||||
{ |
|
||||
$filePath = iconv('UTF-8', 'GBK', $filePath); |
|
||||
if(is_string($filePath) && $filePath !== '') |
|
||||
{ |
|
||||
$fp = null; |
|
||||
$dir = dirname($filePath); |
|
||||
try{ |
|
||||
if(!is_dir($dir)) |
|
||||
{ |
|
||||
mkdir($dir,0755,true); |
|
||||
} |
|
||||
|
|
||||
if(($fp = fopen($filePath, 'w'))) |
|
||||
{ |
|
||||
while(!$body->eof()) |
|
||||
{ |
|
||||
$str = $body->read($this->chunkSize); |
|
||||
fwrite($fp, $str); |
|
||||
} |
|
||||
fflush($fp); |
|
||||
ObsLog::commonLog(DEBUG, "write file %s ok",$filePath); |
|
||||
} |
|
||||
else{ |
|
||||
ObsLog::commonLog(ERROR, "open file error,file path:%s",$filePath); |
|
||||
} |
|
||||
}finally{ |
|
||||
if($fp){ |
|
||||
fclose($fp); |
|
||||
} |
|
||||
$body->close(); |
|
||||
$body = null; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function parseXmlToException($body, $obsException){ |
|
||||
try{ |
|
||||
$xmlErrorBody = trim($body -> getContents()); |
|
||||
if($xmlErrorBody && ($xml = simplexml_load_string($xmlErrorBody))){ |
|
||||
$prefix = $this->getXpathPrefix($xml); |
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'Code')) { |
|
||||
$obsException-> setExceptionCode(strval($tempXml[0])); |
|
||||
} |
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'RequestId')) { |
|
||||
$obsException-> setRequestId(strval($tempXml[0])); |
|
||||
} |
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'Message')) { |
|
||||
$obsException-> setExceptionMessage(strval($tempXml[0])); |
|
||||
} |
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'HostId')) { |
|
||||
$obsException -> setHostId(strval($tempXml[0])); |
|
||||
} |
|
||||
} |
|
||||
}finally{ |
|
||||
$body -> close(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function parseJsonToException($body, $obsException) { |
|
||||
try { |
|
||||
$jsonErrorBody = trim($body -> getContents()); |
|
||||
if ($jsonErrorBody && ($data = json_decode($jsonErrorBody, true))) { |
|
||||
if (is_array($data)) { |
|
||||
if ($data['request_id']) { |
|
||||
$obsException -> setRequestId(strval($data['request_id'])); |
|
||||
} |
|
||||
if ($data['code']) { |
|
||||
$obsException -> setExceptionCode(strval($data['code'])); |
|
||||
} |
|
||||
if ($data['message']) { |
|
||||
$obsException -> setExceptionMessage(strval($data['message'])); |
|
||||
} |
|
||||
} elseif (strlen($data)) { |
|
||||
ObsLog::commonLog(ERROR, "response body %s, and jsonToArray data is %s",$body, $data); |
|
||||
$obsException-> setExceptionMessage("Invalid response data,since it is not json data"); |
|
||||
} |
|
||||
} |
|
||||
} finally { |
|
||||
$body -> close(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function parseJsonToModel($body, $model) { |
|
||||
try{ |
|
||||
$jsonErrorBody = trim($body -> getContents()); |
|
||||
if ($jsonErrorBody && ($jsonArray = json_decode($jsonErrorBody, true))) { |
|
||||
if (is_array($jsonArray)) { |
|
||||
if ($jsonArray['request_id']) { |
|
||||
$model['RequestId'] = strval($jsonArray['request_id']); |
|
||||
} |
|
||||
if ($jsonArray['code']) { |
|
||||
$model['Code'] = strval($jsonArray['code']); |
|
||||
} |
|
||||
if ($jsonArray['message']) { |
|
||||
$model['Message'] = strval($jsonArray['message']); |
|
||||
} |
|
||||
} elseif (strlen($jsonArray)) { |
|
||||
ObsLog::commonLog(ERROR, "response body %s, and jsonToArray data is %s",$body, $jsonArray); |
|
||||
$model['Message'] = "Invalid response data,since it is not json data"; |
|
||||
} |
|
||||
} |
|
||||
} finally { |
|
||||
$body -> close(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function parseXmlToModel($body, $model){ |
|
||||
try{ |
|
||||
$xmlErrorBody = trim($body -> getContents()); |
|
||||
if($xmlErrorBody && ($xml = simplexml_load_string($xmlErrorBody))){ |
|
||||
$prefix = $this->getXpathPrefix($xml); |
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'Code')) { |
|
||||
$model['Code'] = strval($tempXml[0]); |
|
||||
} |
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'RequestId')) { |
|
||||
$model['RequestId'] = strval($tempXml[0]); |
|
||||
} |
|
||||
|
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'HostId')) { |
|
||||
$model['HostId'] = strval($tempXml[0]); |
|
||||
} |
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'Resource')) { |
|
||||
$model['Resource'] = strval($tempXml[0]); |
|
||||
} |
|
||||
|
|
||||
if ($tempXml = $xml->xpath('//'.$prefix . 'Message')) { |
|
||||
$model['Message'] = strval($tempXml[0]); |
|
||||
} |
|
||||
} |
|
||||
}finally { |
|
||||
$body -> close(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected function parseResponse(Model $model, Request $request, Response $response, array $requestConfig) |
|
||||
{ |
|
||||
$statusCode = $response -> getStatusCode(); |
|
||||
$expectedLength = $response -> getHeaderLine('content-length'); |
|
||||
$responseContentType = $response -> getHeaderLine('content-type'); |
|
||||
|
|
||||
$expectedLength = is_numeric($expectedLength) ? floatval($expectedLength) : null; |
|
||||
|
|
||||
$body = new CheckoutStream($response->getBody(), $expectedLength); |
|
||||
|
|
||||
if($statusCode >= 300){ |
|
||||
if($this-> exceptionResponseMode){ |
|
||||
$obsException= new ObsException(); |
|
||||
$obsException-> setRequest($request); |
|
||||
$obsException-> setResponse($response); |
|
||||
$obsException-> setExceptionType($this->isClientError($response) ? 'client' : 'server'); |
|
||||
if ($responseContentType === 'application/json') { |
|
||||
$this->parseJsonToException($body, $obsException); |
|
||||
} else { |
|
||||
$this->parseXmlToException($body, $obsException); |
|
||||
} |
|
||||
throw $obsException; |
|
||||
}else{ |
|
||||
$this->parseCommonHeaders($model, $response); |
|
||||
if ($responseContentType === 'application/json') { |
|
||||
$this->parseJsonToModel($body, $model); |
|
||||
} else { |
|
||||
$this->parseXmlToModel($body, $model); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
}else{ |
|
||||
if(!empty($model)){ |
|
||||
foreach ($model as $key => $value){ |
|
||||
if($key === 'method'){ |
|
||||
continue; |
|
||||
} |
|
||||
if(isset($value['type']) && $value['type'] === 'file'){ |
|
||||
$this->writeFile($value['value'], $body, $expectedLength); |
|
||||
} |
|
||||
$model[$key] = $value['value']; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if(isset($requestConfig['responseParameters'])){ |
|
||||
$responseParameters = $requestConfig['responseParameters']; |
|
||||
if(isset($responseParameters['type']) && $responseParameters['type'] === 'object'){ |
|
||||
$responseParameters = $responseParameters['properties']; |
|
||||
} |
|
||||
$this->parseItems($responseParameters, $model, $response, $body); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$model['HttpStatusCode'] = $statusCode; |
|
||||
$model['Reason'] = $response -> getReasonPhrase(); |
|
||||
} |
|
||||
|
|
||||
protected function getXpathPrefix($xml) |
|
||||
{ |
|
||||
$namespaces = $xml -> getDocNamespaces(); |
|
||||
if (isset($namespaces[''])) { |
|
||||
$xml->registerXPathNamespace('ns', $namespaces['']); |
|
||||
$prefix = 'ns:'; |
|
||||
} else { |
|
||||
$prefix = ''; |
|
||||
} |
|
||||
return $prefix; |
|
||||
} |
|
||||
|
|
||||
protected function buildException(Request $request, RequestException $exception, $message) |
|
||||
{ |
|
||||
$response = $exception-> hasResponse() ? $exception-> getResponse() : null; |
|
||||
$obsException= new ObsException($message ? $message : $exception-> getMessage()); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
$obsException-> setRequest($request); |
|
||||
if($response){ |
|
||||
$obsException-> setResponse($response); |
|
||||
$obsException-> setExceptionType($this->isClientError($response) ? 'client' : 'server'); |
|
||||
if ($this->isJsonResponse($response)) { |
|
||||
$this->parseJsonToException($response -> getBody(), $obsException); |
|
||||
} else { |
|
||||
$this->parseXmlToException($response -> getBody(), $obsException); |
|
||||
} |
|
||||
if ($obsException->getRequestId() === null) { |
|
||||
$prefix = strcasecmp($this->signature, 'obs' ) === 0 ? 'x-obs-' : 'x-amz-'; |
|
||||
$requestId = $response->getHeaderLine($prefix . 'request-id'); |
|
||||
$obsException->setRequestId($requestId); |
|
||||
} |
|
||||
} |
|
||||
return $obsException; |
|
||||
} |
|
||||
|
|
||||
protected function parseExceptionAsync(Request $request, RequestException $exception, $message=null) |
|
||||
{ |
|
||||
return $this->buildException($request, $exception, $message); |
|
||||
} |
|
||||
|
|
||||
protected function parseException(Model $model, Request $request, RequestException $exception, $message=null) |
|
||||
{ |
|
||||
$response = $exception-> hasResponse() ? $exception-> getResponse() : null; |
|
||||
if($this-> exceptionResponseMode){ |
|
||||
throw $this->buildException($request, $exception, $message); |
|
||||
}else{ |
|
||||
if($response){ |
|
||||
$model['HttpStatusCode'] = $response -> getStatusCode(); |
|
||||
$model['Reason'] = $response -> getReasonPhrase(); |
|
||||
$this->parseXmlToModel($response -> getBody(), $model); |
|
||||
}else{ |
|
||||
$model['HttpStatusCode'] = -1; |
|
||||
$model['Message'] = $exception -> getMessage(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,140 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Resource; |
|
||||
|
|
||||
class Constants { |
|
||||
const ALLOWED_RESOURCE_PARAMTER_NAMES = [ |
|
||||
'acl', |
|
||||
'policy', |
|
||||
'torrent', |
|
||||
'logging', |
|
||||
'location', |
|
||||
'storageinfo', |
|
||||
'quota', |
|
||||
'storagepolicy', |
|
||||
'requestpayment', |
|
||||
'versions', |
|
||||
'versioning', |
|
||||
'versionid', |
|
||||
'uploads', |
|
||||
'uploadid', |
|
||||
'partnumber', |
|
||||
'website', |
|
||||
'notification', |
|
||||
'lifecycle', |
|
||||
'deletebucket', |
|
||||
'delete', |
|
||||
'cors', |
|
||||
'restore', |
|
||||
'tagging', |
|
||||
'response-content-type', |
|
||||
'response-content-language', |
|
||||
'response-expires', |
|
||||
'response-cache-control', |
|
||||
'response-content-disposition', |
|
||||
'response-content-encoding', |
|
||||
'x-image-process', |
|
||||
|
|
||||
'backtosource', |
|
||||
'storageclass', |
|
||||
'replication', |
|
||||
'append', |
|
||||
'position', |
|
||||
'x-oss-process', |
|
||||
|
|
||||
'CDNNotifyConfiguration', |
|
||||
'attname', |
|
||||
'customdomain', |
|
||||
'directcoldaccess', |
|
||||
'encryption', |
|
||||
'inventory', |
|
||||
'length', |
|
||||
'metadata', |
|
||||
'modify', |
|
||||
'name', |
|
||||
'rename', |
|
||||
'truncate', |
|
||||
'x-image-save-bucket', |
|
||||
'x-image-save-object', |
|
||||
'x-obs-security-token', |
|
||||
'x-obs-callback', |
|
||||
]; |
|
||||
const ALLOWED_REQUEST_HTTP_HEADER_METADATA_NAMES = [ |
|
||||
'content-type', |
|
||||
'content-md5', |
|
||||
'content-length', |
|
||||
'content-language', |
|
||||
'expires', |
|
||||
'origin', |
|
||||
'cache-control', |
|
||||
'content-disposition', |
|
||||
'content-encoding', |
|
||||
'access-control-request-method', |
|
||||
'access-control-request-headers', |
|
||||
'x-default-storage-class', |
|
||||
'location', |
|
||||
'date', |
|
||||
'etag', |
|
||||
'range', |
|
||||
'host', |
|
||||
'if-modified-since', |
|
||||
'if-unmodified-since', |
|
||||
'if-match', |
|
||||
'if-none-match', |
|
||||
'last-modified', |
|
||||
'content-range', |
|
||||
|
|
||||
'success-action-redirect' |
|
||||
]; |
|
||||
const ALLOWED_RESPONSE_HTTP_HEADER_METADATA_NAMES = [ |
|
||||
'content-type', |
|
||||
'content-md5', |
|
||||
'content-length', |
|
||||
'content-language', |
|
||||
'expires', |
|
||||
'origin', |
|
||||
'cache-control', |
|
||||
'content-disposition', |
|
||||
'content-encoding', |
|
||||
'x-default-storage-class', |
|
||||
'location', |
|
||||
'date', |
|
||||
'etag', |
|
||||
'host', |
|
||||
'last-modified', |
|
||||
'content-range', |
|
||||
'x-reserved', |
|
||||
'access-control-allow-origin', |
|
||||
'access-control-allow-headers', |
|
||||
'access-control-max-age', |
|
||||
'access-control-allow-methods', |
|
||||
'access-control-expose-headers', |
|
||||
'connection' |
|
||||
]; |
|
||||
|
|
||||
public static function selectConstants($signature) { |
|
||||
$signature = (strcasecmp ( $signature, 'obs' ) === 0) ? 'OBS' : 'V2'; |
|
||||
return __NAMESPACE__ . '\\' . $signature . 'Constants'; |
|
||||
} |
|
||||
|
|
||||
public static function selectRequestResource($signature) { |
|
||||
$signature = (strcasecmp ( $signature, 'obs' ) === 0) ? 'OBS' : 'V2'; |
|
||||
return (__NAMESPACE__ . '\\' . $signature . 'RequestResource'); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,35 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Resource; |
|
||||
|
|
||||
class OBSConstants extends Constants { |
|
||||
const FLAG = 'OBS'; |
|
||||
const METADATA_PREFIX = 'x-obs-meta-'; |
|
||||
const HEADER_PREFIX = 'x-obs-'; |
|
||||
const ALTERNATIVE_DATE_HEADER = 'x-obs-date'; |
|
||||
const SECURITY_TOKEN_HEAD = 'x-obs-security-token'; |
|
||||
const TEMPURL_AK_HEAD = 'AccessKeyId'; |
|
||||
|
|
||||
const COMMON_HEADERS = [ |
|
||||
'content-length' => 'ContentLength', |
|
||||
'date' => 'Date', |
|
||||
'x-obs-request-id' => 'RequestId', |
|
||||
'x-obs-id-2' => 'Id2', |
|
||||
'x-reserved' => 'Reserved' |
|
||||
]; |
|
||||
} |
|
||||
File diff suppressed because it is too large
@ -1,38 +0,0 @@ |
|||||
<?php |
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Resource; |
|
||||
|
|
||||
class V2Constants extends Constants { |
|
||||
const FLAG = 'AWS'; |
|
||||
const METADATA_PREFIX = 'x-amz-meta-'; |
|
||||
const HEADER_PREFIX = 'x-amz-'; |
|
||||
const ALTERNATIVE_DATE_HEADER = 'x-amz-date'; |
|
||||
const SECURITY_TOKEN_HEAD = 'x-amz-security-token'; |
|
||||
const TEMPURL_AK_HEAD = 'AWSAccessKeyId'; |
|
||||
|
|
||||
const GROUP_ALL_USERS_PREFIX = 'http://acs.amazonaws.com/groups/global/'; |
|
||||
const GROUP_AUTHENTICATED_USERS_PREFIX = 'http://acs.amazonaws.com/groups/global/'; |
|
||||
const GROUP_LOG_DELIVERY_PREFIX = 'http://acs.amazonaws.com/groups/s3/'; |
|
||||
|
|
||||
const COMMON_HEADERS = [ |
|
||||
'content-length' => 'ContentLength', |
|
||||
'date' => 'Date', |
|
||||
'x-amz-request-id' => 'RequestId', |
|
||||
'x-amz-id-2' => 'Id2', |
|
||||
'x-reserved' => 'Reserved' |
|
||||
]; |
|
||||
} |
|
||||
File diff suppressed because it is too large
@ -1,726 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal; |
|
||||
|
|
||||
use GuzzleHttp\Psr7; |
|
||||
use Obs\Log\ObsLog; |
|
||||
use GuzzleHttp\Psr7\Request; |
|
||||
use GuzzleHttp\Psr7\Response; |
|
||||
use GuzzleHttp\Exception\RequestException; |
|
||||
use GuzzleHttp\Exception\ConnectException; |
|
||||
use Obs\Internal\Common\Model; |
|
||||
use Obs\Internal\Resource\V2Constants; |
|
||||
use Obs\ObsException; |
|
||||
use Obs\Internal\Signature\V4Signature; |
|
||||
use Obs\Internal\Signature\DefaultSignature; |
|
||||
use GuzzleHttp\Client; |
|
||||
use Obs\Internal\Resource\Constants; |
|
||||
use Psr\Http\Message\StreamInterface; |
|
||||
use Obs\Internal\Resource\V2RequestResource; |
|
||||
|
|
||||
trait SendRequestTrait |
|
||||
{ |
|
||||
protected $ak; |
|
||||
|
|
||||
protected $sk; |
|
||||
|
|
||||
protected $securityToken = false; |
|
||||
|
|
||||
protected $endpoint = ''; |
|
||||
|
|
||||
protected $pathStyle = false; |
|
||||
|
|
||||
protected $region = 'region'; |
|
||||
|
|
||||
protected $signature = 'obs'; |
|
||||
|
|
||||
protected $sslVerify = false; |
|
||||
|
|
||||
protected $maxRetryCount = 3; |
|
||||
|
|
||||
protected $timeout = 0; |
|
||||
|
|
||||
protected $socketTimeout = 60; |
|
||||
|
|
||||
protected $connectTimeout = 60; |
|
||||
|
|
||||
protected $isCname = false; |
|
||||
|
|
||||
/** @var Client */ |
|
||||
protected $httpClient; |
|
||||
|
|
||||
public function createSignedUrl(array $args=[]){ |
|
||||
if (strcasecmp($this -> signature, 'v4') === 0) { |
|
||||
return $this -> createV4SignedUrl($args); |
|
||||
} |
|
||||
return $this->createCommonSignedUrl($this->signature,$args); |
|
||||
} |
|
||||
|
|
||||
public function createV2SignedUrl(array $args=[]) { |
|
||||
return $this->createCommonSignedUrl( 'v2',$args); |
|
||||
} |
|
||||
|
|
||||
private function createCommonSignedUrl(string $signature,array $args=[]) { |
|
||||
if(!isset($args['Method'])){ |
|
||||
$obsException = new ObsException('Method param must be specified, allowed values: GET | PUT | HEAD | POST | DELETE | OPTIONS'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
$method = strval($args['Method']); |
|
||||
$bucketName = isset($args['Bucket'])? strval($args['Bucket']): null; |
|
||||
$objectKey = isset($args['Key'])? strval($args['Key']): null; |
|
||||
$specialParam = isset($args['SpecialParam'])? strval($args['SpecialParam']): null; |
|
||||
$expires = isset($args['Expires']) && is_numeric($args['Expires']) ? intval($args['Expires']): 300; |
|
||||
|
|
||||
$headers = []; |
|
||||
if(isset($args['Headers']) && is_array($args['Headers']) ){ |
|
||||
foreach ($args['Headers'] as $key => $val){ |
|
||||
if(is_string($key) && $key !== ''){ |
|
||||
$headers[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
$queryParams = []; |
|
||||
if(isset($args['QueryParams']) && is_array($args['QueryParams']) ){ |
|
||||
foreach ($args['QueryParams'] as $key => $val){ |
|
||||
if(is_string($key) && $key !== ''){ |
|
||||
$queryParams[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$constants = Constants::selectConstants($signature); |
|
||||
if($this->securityToken && !isset($queryParams[$constants::SECURITY_TOKEN_HEAD])){ |
|
||||
$queryParams[$constants::SECURITY_TOKEN_HEAD] = $this->securityToken; |
|
||||
} |
|
||||
|
|
||||
$sign = new DefaultSignature($this->ak, $this->sk, $this->pathStyle, $this->endpoint, $method, $this->signature, $this->securityToken, $this->isCname); |
|
||||
|
|
||||
$url = parse_url($this->endpoint); |
|
||||
$host = $url['host']; |
|
||||
|
|
||||
$result = ''; |
|
||||
|
|
||||
if($bucketName){ |
|
||||
if($this-> pathStyle){ |
|
||||
$result = '/' . $bucketName; |
|
||||
}else{ |
|
||||
$host = $this->isCname ? $host : $bucketName . '.' . $host; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$headers['Host'] = $host; |
|
||||
|
|
||||
if($objectKey){ |
|
||||
$objectKey = $sign ->urlencodeWithSafe($objectKey); |
|
||||
$result .= '/' . $objectKey; |
|
||||
} |
|
||||
|
|
||||
$result .= '?'; |
|
||||
|
|
||||
if($specialParam){ |
|
||||
$queryParams[$specialParam] = ''; |
|
||||
} |
|
||||
|
|
||||
$queryParams[$constants::TEMPURL_AK_HEAD] = $this->ak; |
|
||||
|
|
||||
|
|
||||
if(!is_numeric($expires) || $expires < 0){ |
|
||||
$expires = 300; |
|
||||
} |
|
||||
$expires = intval($expires) + intval(microtime(true)); |
|
||||
|
|
||||
$queryParams['Expires'] = strval($expires); |
|
||||
|
|
||||
$_queryParams = []; |
|
||||
|
|
||||
foreach ($queryParams as $key => $val){ |
|
||||
$key = $sign -> urlencodeWithSafe($key); |
|
||||
$val = $sign -> urlencodeWithSafe($val); |
|
||||
$_queryParams[$key] = $val; |
|
||||
$result .= $key; |
|
||||
if($val){ |
|
||||
$result .= '=' . $val; |
|
||||
} |
|
||||
$result .= '&'; |
|
||||
} |
|
||||
|
|
||||
$canonicalstring = $sign ->makeCanonicalstring($method, $headers, $_queryParams, $bucketName, $objectKey, $expires); |
|
||||
$signatureContent = base64_encode(hash_hmac('sha1', $canonicalstring, $this->sk, true)); |
|
||||
|
|
||||
$result .= 'Signature=' . $sign->urlencodeWithSafe($signatureContent); |
|
||||
|
|
||||
$model = new Model(); |
|
||||
$model['ActualSignedRequestHeaders'] = $headers; |
|
||||
$model['SignedUrl'] = $url['scheme'] . '://' . $host . ':' . (isset($url['port']) ? $url['port'] : (strtolower($url['scheme']) === 'https' ? '443' : '80')) . $result; |
|
||||
return $model; |
|
||||
} |
|
||||
|
|
||||
public function createV4SignedUrl(array $args=[]){ |
|
||||
if(!isset($args['Method'])){ |
|
||||
$obsException= new ObsException('Method param must be specified, allowed values: GET | PUT | HEAD | POST | DELETE | OPTIONS'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
$method = strval($args['Method']); |
|
||||
$bucketName = isset($args['Bucket'])? strval($args['Bucket']): null; |
|
||||
$objectKey = isset($args['Key'])? strval($args['Key']): null; |
|
||||
$specialParam = isset($args['SpecialParam'])? strval($args['SpecialParam']): null; |
|
||||
$expires = isset($args['Expires']) && is_numeric($args['Expires']) ? intval($args['Expires']): 300; |
|
||||
$headers = []; |
|
||||
if(isset($args['Headers']) && is_array($args['Headers']) ){ |
|
||||
foreach ($args['Headers'] as $key => $val){ |
|
||||
if(is_string($key) && $key !== ''){ |
|
||||
$headers[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$queryParams = []; |
|
||||
if(isset($args['QueryParams']) && is_array($args['QueryParams']) ){ |
|
||||
foreach ($args['QueryParams'] as $key => $val){ |
|
||||
if(is_string($key) && $key !== ''){ |
|
||||
$queryParams[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($this->securityToken && !isset($queryParams['x-amz-security-token'])){ |
|
||||
$queryParams['x-amz-security-token'] = $this->securityToken; |
|
||||
} |
|
||||
|
|
||||
$v4 = new V4Signature($this->ak, $this->sk, $this->pathStyle, $this->endpoint, $this->region, $method, $this->signature, $this->securityToken, $this->isCname); |
|
||||
|
|
||||
$url = parse_url($this->endpoint); |
|
||||
$host = $url['host']; |
|
||||
|
|
||||
$result = ''; |
|
||||
|
|
||||
if($bucketName){ |
|
||||
if($this-> pathStyle){ |
|
||||
$result = '/' . $bucketName; |
|
||||
}else{ |
|
||||
$host = $this->isCname ? $host : $bucketName . '.' . $host; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$headers['Host'] = $host; |
|
||||
|
|
||||
if($objectKey){ |
|
||||
$objectKey = $v4 -> urlencodeWithSafe($objectKey); |
|
||||
$result .= '/' . $objectKey; |
|
||||
} |
|
||||
|
|
||||
$result .= '?'; |
|
||||
|
|
||||
if($specialParam){ |
|
||||
$queryParams[$specialParam] = ''; |
|
||||
} |
|
||||
|
|
||||
if(!is_numeric($expires) || $expires < 0){ |
|
||||
$expires = 300; |
|
||||
} |
|
||||
|
|
||||
$expires = strval($expires); |
|
||||
|
|
||||
$date = isset($headers['date']) ? $headers['date'] : (isset($headers['Date']) ? $headers['Date'] : null); |
|
||||
|
|
||||
$timestamp = $date ? date_create_from_format('D, d M Y H:i:s \G\M\T', $date, new \DateTimeZone ('UTC')) -> getTimestamp() |
|
||||
:time(); |
|
||||
|
|
||||
$longDate = gmdate('Ymd\THis\Z', $timestamp); |
|
||||
$shortDate = substr($longDate, 0, 8); |
|
||||
|
|
||||
$headers['host'] = $host; |
|
||||
if(isset($url['port'])){ |
|
||||
$port = $url['port']; |
|
||||
if($port !== 443 && $port !== 80){ |
|
||||
$headers['host'] = $headers['host'] . ':' . $port; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$signedHeaders = $v4 -> getSignedHeaders($headers); |
|
||||
|
|
||||
$queryParams['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256'; |
|
||||
$queryParams['X-Amz-Credential'] = $v4 -> getCredential($shortDate); |
|
||||
$queryParams['X-Amz-Date'] = $longDate; |
|
||||
$queryParams['X-Amz-Expires'] = $expires; |
|
||||
$queryParams['X-Amz-SignedHeaders'] = $signedHeaders; |
|
||||
|
|
||||
$_queryParams = []; |
|
||||
|
|
||||
foreach ($queryParams as $key => $val){ |
|
||||
$key = rawurlencode($key); |
|
||||
$val = rawurlencode($val); |
|
||||
$_queryParams[$key] = $val; |
|
||||
$result .= $key; |
|
||||
if($val){ |
|
||||
$result .= '=' . $val; |
|
||||
} |
|
||||
$result .= '&'; |
|
||||
} |
|
||||
|
|
||||
$canonicalstring = $v4 -> makeCanonicalstring($method, $headers, $_queryParams, $bucketName, $objectKey, $signedHeaders, 'UNSIGNED-PAYLOAD'); |
|
||||
|
|
||||
$signatureContent = $v4 -> getSignature($canonicalstring, $longDate, $shortDate); |
|
||||
|
|
||||
$result .= 'X-Amz-Signature=' . $v4 -> urlencodeWithSafe($signatureContent); |
|
||||
|
|
||||
$model = new Model(); |
|
||||
$model['ActualSignedRequestHeaders'] = $headers; |
|
||||
$model['SignedUrl'] = $url['scheme'] . '://' . $host . ':' . (isset($url['port']) ? $url['port'] : (strtolower($url['scheme']) === 'https' ? '443' : '80')) . $result; |
|
||||
return $model; |
|
||||
} |
|
||||
|
|
||||
public function createPostSignature(array $args=[]) { |
|
||||
if (strcasecmp($this -> signature, 'v4') === 0) { |
|
||||
return $this -> createV4PostSignature($args); |
|
||||
} |
|
||||
|
|
||||
$bucketName = isset($args['Bucket'])? strval($args['Bucket']): null; |
|
||||
$objectKey = isset($args['Key'])? strval($args['Key']): null; |
|
||||
$expires = isset($args['Expires']) && is_numeric($args['Expires']) ? intval($args['Expires']): 300; |
|
||||
|
|
||||
$formParams = []; |
|
||||
|
|
||||
if(isset($args['FormParams']) && is_array($args['FormParams'])){ |
|
||||
foreach ($args['FormParams'] as $key => $val){ |
|
||||
$formParams[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$constants = Constants::selectConstants($this -> signature); |
|
||||
if($this->securityToken && !isset($formParams[$constants::SECURITY_TOKEN_HEAD])){ |
|
||||
$formParams[$constants::SECURITY_TOKEN_HEAD] = $this->securityToken; |
|
||||
} |
|
||||
|
|
||||
$timestamp = time(); |
|
||||
$expires = gmdate('Y-m-d\TH:i:s\Z', $timestamp + $expires); |
|
||||
|
|
||||
if($bucketName){ |
|
||||
$formParams['bucket'] = $bucketName; |
|
||||
} |
|
||||
|
|
||||
if($objectKey){ |
|
||||
$formParams['key'] = $objectKey; |
|
||||
} |
|
||||
|
|
||||
$policy = []; |
|
||||
|
|
||||
$policy[] = '{"expiration":"'; |
|
||||
$policy[] = $expires; |
|
||||
$policy[] = '", "conditions":['; |
|
||||
|
|
||||
$matchAnyBucket = true; |
|
||||
$matchAnyKey = true; |
|
||||
|
|
||||
$conditionAllowKeys = ['acl', 'bucket', 'key', 'success_action_redirect', 'redirect', 'success_action_status']; |
|
||||
|
|
||||
foreach($formParams as $key => $val){ |
|
||||
if($key){ |
|
||||
$key = strtolower(strval($key)); |
|
||||
|
|
||||
if($key === 'bucket'){ |
|
||||
$matchAnyBucket = false; |
|
||||
}else if($key === 'key'){ |
|
||||
$matchAnyKey = false; |
|
||||
} |
|
||||
|
|
||||
if(!in_array($key, Constants::ALLOWED_REQUEST_HTTP_HEADER_METADATA_NAMES) && strpos($key, $constants::HEADER_PREFIX) !== 0 && !in_array($key, $conditionAllowKeys)){ |
|
||||
$key = $constants::METADATA_PREFIX . $key; |
|
||||
} |
|
||||
|
|
||||
$policy[] = '{"'; |
|
||||
$policy[] = $key; |
|
||||
$policy[] = '":"'; |
|
||||
$policy[] = $val !== null ? strval($val) : ''; |
|
||||
$policy[] = '"},'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($matchAnyBucket){ |
|
||||
$policy[] = '["starts-with", "$bucket", ""],'; |
|
||||
} |
|
||||
|
|
||||
if($matchAnyKey){ |
|
||||
$policy[] = '["starts-with", "$key", ""],'; |
|
||||
} |
|
||||
|
|
||||
$policy[] = ']}'; |
|
||||
|
|
||||
$originPolicy = implode('', $policy); |
|
||||
|
|
||||
$policy = base64_encode($originPolicy); |
|
||||
|
|
||||
$signatureContent = base64_encode(hash_hmac('sha1', $policy, $this->sk, true)); |
|
||||
|
|
||||
$model = new Model(); |
|
||||
$model['OriginPolicy'] = $originPolicy; |
|
||||
$model['Policy'] = $policy; |
|
||||
$model['Signature'] = $signatureContent; |
|
||||
return $model; |
|
||||
} |
|
||||
|
|
||||
public function createV4PostSignature(array $args=[]){ |
|
||||
$bucketName = isset($args['Bucket'])? strval($args['Bucket']): null; |
|
||||
$objectKey = isset($args['Key'])? strval($args['Key']): null; |
|
||||
$expires = isset($args['Expires']) && is_numeric($args['Expires']) ? intval($args['Expires']): 300; |
|
||||
|
|
||||
$formParams = []; |
|
||||
|
|
||||
if(isset($args['FormParams']) && is_array($args['FormParams'])){ |
|
||||
foreach ($args['FormParams'] as $key => $val){ |
|
||||
$formParams[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($this->securityToken && !isset($formParams['x-amz-security-token'])){ |
|
||||
$formParams['x-amz-security-token'] = $this->securityToken; |
|
||||
} |
|
||||
|
|
||||
$timestamp = time(); |
|
||||
$longDate = gmdate('Ymd\THis\Z', $timestamp); |
|
||||
$shortDate = substr($longDate, 0, 8); |
|
||||
|
|
||||
$credential = sprintf('%s/%s/%s/s3/aws4_request', $this->ak, $shortDate, $this->region); |
|
||||
|
|
||||
$expires = gmdate('Y-m-d\TH:i:s\Z', $timestamp + $expires); |
|
||||
|
|
||||
$formParams['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256'; |
|
||||
$formParams['X-Amz-Date'] = $longDate; |
|
||||
$formParams['X-Amz-Credential'] = $credential; |
|
||||
|
|
||||
if($bucketName){ |
|
||||
$formParams['bucket'] = $bucketName; |
|
||||
} |
|
||||
|
|
||||
if($objectKey){ |
|
||||
$formParams['key'] = $objectKey; |
|
||||
} |
|
||||
|
|
||||
$policy = []; |
|
||||
|
|
||||
$policy[] = '{"expiration":"'; |
|
||||
$policy[] = $expires; |
|
||||
$policy[] = '", "conditions":['; |
|
||||
|
|
||||
$matchAnyBucket = true; |
|
||||
$matchAnyKey = true; |
|
||||
|
|
||||
$conditionAllowKeys = ['acl', 'bucket', 'key', 'success_action_redirect', 'redirect', 'success_action_status']; |
|
||||
|
|
||||
foreach($formParams as $key => $val){ |
|
||||
if($key){ |
|
||||
$key = strtolower(strval($key)); |
|
||||
|
|
||||
if($key === 'bucket'){ |
|
||||
$matchAnyBucket = false; |
|
||||
}else if($key === 'key'){ |
|
||||
$matchAnyKey = false; |
|
||||
} |
|
||||
|
|
||||
if(!in_array($key, Constants::ALLOWED_REQUEST_HTTP_HEADER_METADATA_NAMES) && strpos($key, V2Constants::HEADER_PREFIX) !== 0 && !in_array($key, $conditionAllowKeys)){ |
|
||||
$key = V2Constants::METADATA_PREFIX . $key; |
|
||||
} |
|
||||
|
|
||||
$policy[] = '{"'; |
|
||||
$policy[] = $key; |
|
||||
$policy[] = '":"'; |
|
||||
$policy[] = $val !== null ? strval($val) : ''; |
|
||||
$policy[] = '"},'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($matchAnyBucket){ |
|
||||
$policy[] = '["starts-with", "$bucket", ""],'; |
|
||||
} |
|
||||
|
|
||||
if($matchAnyKey){ |
|
||||
$policy[] = '["starts-with", "$key", ""],'; |
|
||||
} |
|
||||
|
|
||||
$policy[] = ']}'; |
|
||||
|
|
||||
$originPolicy = implode('', $policy); |
|
||||
|
|
||||
$policy = base64_encode($originPolicy); |
|
||||
|
|
||||
$dateKey = hash_hmac('sha256', $shortDate, 'AWS4' . $this -> sk, true); |
|
||||
$regionKey = hash_hmac('sha256', $this->region, $dateKey, true); |
|
||||
$serviceKey = hash_hmac('sha256', 's3', $regionKey, true); |
|
||||
$signingKey = hash_hmac('sha256', 'aws4_request', $serviceKey, true); |
|
||||
$signatureContent = hash_hmac('sha256', $policy, $signingKey); |
|
||||
|
|
||||
$model = new Model(); |
|
||||
$model['OriginPolicy'] = $originPolicy; |
|
||||
$model['Policy'] = $policy; |
|
||||
$model['Algorithm'] = $formParams['X-Amz-Algorithm']; |
|
||||
$model['Credential'] = $formParams['X-Amz-Credential']; |
|
||||
$model['Date'] = $formParams['X-Amz-Date']; |
|
||||
$model['Signature'] = $signatureContent; |
|
||||
return $model; |
|
||||
} |
|
||||
|
|
||||
public function __call($originMethod, $args) |
|
||||
{ |
|
||||
$method = $originMethod; |
|
||||
|
|
||||
$contents = Constants::selectRequestResource($this->signature); |
|
||||
$resource = &$contents::$RESOURCE_ARRAY; |
|
||||
$async = false; |
|
||||
if(strpos($method, 'Async') === (strlen($method) - 5)){ |
|
||||
$method = substr($method, 0, strlen($method) - 5); |
|
||||
$async = true; |
|
||||
} |
|
||||
|
|
||||
if(isset($resource['aliases'][$method])){ |
|
||||
$method = $resource['aliases'][$method]; |
|
||||
} |
|
||||
|
|
||||
$method = lcfirst($method); |
|
||||
|
|
||||
|
|
||||
$operation = isset($resource['operations'][$method]) ? |
|
||||
$resource['operations'][$method] : null; |
|
||||
|
|
||||
if(!$operation){ |
|
||||
ObsLog::commonLog(WARNING, 'unknow method ' . $originMethod); |
|
||||
$obsException= new ObsException('unknow method '. $originMethod); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
|
|
||||
$start = microtime(true); |
|
||||
if(!$async){ |
|
||||
ObsLog::commonLog(INFO, 'enter method '. $originMethod. '...'); |
|
||||
$model = new Model(); |
|
||||
$model['method'] = $method; |
|
||||
$params = empty($args) ? [] : $args[0]; |
|
||||
$this->checkMimeType($method, $params); |
|
||||
$this->doRequest($model, $operation, $params); |
|
||||
ObsLog::commonLog(INFO, 'obsclient cost ' . round(microtime(true) - $start, 3) * 1000 . ' ms to execute '. $originMethod); |
|
||||
unset($model['method']); |
|
||||
return $model; |
|
||||
}else{ |
|
||||
if(empty($args) || !(is_callable($callback = $args[count($args) -1]))){ |
|
||||
ObsLog::commonLog(WARNING, 'async method ' . $originMethod . ' must pass a CallbackInterface as param'); |
|
||||
$obsException= new ObsException('async method ' . $originMethod . ' must pass a CallbackInterface as param'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
ObsLog::commonLog(INFO, 'enter method '. $originMethod. '...'); |
|
||||
$params = count($args) === 1 ? [] : $args[0]; |
|
||||
$this->checkMimeType($method, $params); |
|
||||
$model = new Model(); |
|
||||
$model['method'] = $method; |
|
||||
return $this->doRequestAsync($model, $operation, $params, $callback, $start, $originMethod); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private function checkMimeType($method, &$params){ |
|
||||
// fix bug that guzzlehttp lib will add the content-type if not set |
|
||||
if(($method === 'putObject' || $method === 'initiateMultipartUpload' || $method === 'uploadPart') && (!isset($params['ContentType']) || $params['ContentType'] === null)){ |
|
||||
if(isset($params['Key'])){ |
|
||||
try { |
|
||||
$params['ContentType'] = Psr7\mimetype_from_filename($params['Key']); |
|
||||
} catch (\Throwable $e) { |
|
||||
$params['ContentType'] = Psr7\MimeType::fromFilename($params['Key']); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if((!isset($params['ContentType']) || $params['ContentType'] === null) && isset($params['SourceFile'])){ |
|
||||
try { |
|
||||
$params['ContentType'] = Psr7\mimetype_from_filename($params['SourceFile']); |
|
||||
} catch (\Throwable $e) { |
|
||||
$params['ContentType'] = Psr7\MimeType::fromFilename($params['SourceFile']); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if(!isset($params['ContentType']) || $params['ContentType'] === null){ |
|
||||
$params['ContentType'] = 'binary/octet-stream'; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected function makeRequest($model, &$operation, $params, $endpoint = null) |
|
||||
{ |
|
||||
if($endpoint === null){ |
|
||||
$endpoint = $this->endpoint; |
|
||||
} |
|
||||
$signatureInterface = strcasecmp($this-> signature, 'v4') === 0 ? |
|
||||
new V4Signature($this->ak, $this->sk, $this->pathStyle, $endpoint, $this->region, $model['method'], $this->signature, $this->securityToken, $this->isCname) : |
|
||||
new DefaultSignature($this->ak, $this->sk, $this->pathStyle, $endpoint, $model['method'], $this->signature, $this->securityToken, $this->isCname); |
|
||||
$authResult = $signatureInterface -> doAuth($operation, $params, $model); |
|
||||
$httpMethod = $authResult['method']; |
|
||||
ObsLog::commonLog(DEBUG, 'perform '. strtolower($httpMethod) . ' request with url ' . $authResult['requestUrl']); |
|
||||
ObsLog::commonLog(DEBUG, 'cannonicalRequest:' . $authResult['cannonicalRequest']); |
|
||||
ObsLog::commonLog(DEBUG, 'request headers ' . var_export($authResult['headers'],true)); |
|
||||
$authResult['headers']['User-Agent'] = self::default_user_agent(); |
|
||||
if($model['method'] === 'putObject'){ |
|
||||
$model['ObjectURL'] = ['value' => $authResult['requestUrl']]; |
|
||||
} |
|
||||
return new Request($httpMethod, $authResult['requestUrl'], $authResult['headers'], $authResult['body']); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
protected function doRequest($model, &$operation, $params, $endpoint = null) |
|
||||
{ |
|
||||
$request = $this -> makeRequest($model, $operation, $params, $endpoint); |
|
||||
$this->sendRequest($model, $operation, $params, $request); |
|
||||
} |
|
||||
|
|
||||
protected function sendRequest($model, &$operation, $params, $request, $requestCount = 1) |
|
||||
{ |
|
||||
$start = microtime(true); |
|
||||
$saveAsStream = false; |
|
||||
if(isset($operation['stream']) && $operation['stream']){ |
|
||||
$saveAsStream = isset($params['SaveAsStream']) ? $params['SaveAsStream'] : false; |
|
||||
|
|
||||
if(isset($params['SaveAsFile'])){ |
|
||||
if($saveAsStream){ |
|
||||
$obsException = new ObsException('SaveAsStream cannot be used with SaveAsFile together'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
$saveAsStream = true; |
|
||||
} |
|
||||
if(isset($params['FilePath'])){ |
|
||||
if($saveAsStream){ |
|
||||
$obsException = new ObsException('SaveAsStream cannot be used with FilePath together'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
$saveAsStream = true; |
|
||||
} |
|
||||
|
|
||||
if(isset($params['SaveAsFile']) && isset($params['FilePath'])){ |
|
||||
$obsException = new ObsException('SaveAsFile cannot be used with FilePath together'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$promise = $this->httpClient->sendAsync($request, ['stream' => $saveAsStream])->then( |
|
||||
function(Response $response) use ($model, $operation, $params, $request, $requestCount, $start){ |
|
||||
|
|
||||
ObsLog::commonLog(INFO, 'http request cost ' . round(microtime(true) - $start, 3) * 1000 . ' ms'); |
|
||||
$statusCode = $response -> getStatusCode(); |
|
||||
$readable = isset($params['Body']) && ($params['Body'] instanceof StreamInterface || is_resource($params['Body'])); |
|
||||
if($statusCode >= 300 && $statusCode <400 && $statusCode !== 304 && !$readable && $requestCount <= $this->maxRetryCount){ |
|
||||
if($location = $response -> getHeaderLine('location')){ |
|
||||
$url = parse_url($this->endpoint); |
|
||||
$newUrl = parse_url($location); |
|
||||
$scheme = (isset($newUrl['scheme']) ? $newUrl['scheme'] : $url['scheme']); |
|
||||
$defaultPort = strtolower($scheme) === 'https' ? '443' : '80'; |
|
||||
$this->doRequest($model, $operation, $params, $scheme. '://' . $newUrl['host'] . |
|
||||
':' . (isset($newUrl['port']) ? $newUrl['port'] : $defaultPort)); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
$this -> parseResponse($model, $request, $response, $operation); |
|
||||
}, |
|
||||
function (RequestException $exception) use ($model, $operation, $params, $request, $requestCount, $start) { |
|
||||
|
|
||||
ObsLog::commonLog(INFO, 'http request cost ' . round(microtime(true) - $start, 3) * 1000 . ' ms'); |
|
||||
$message = null; |
|
||||
if($exception instanceof ConnectException){ |
|
||||
if($requestCount <= $this->maxRetryCount){ |
|
||||
$this -> sendRequest($model, $operation, $params, $request, $requestCount + 1); |
|
||||
return; |
|
||||
}else{ |
|
||||
$message = 'Exceeded retry limitation, max retry count:'. $this->maxRetryCount . ', error message:' . $exception -> getMessage(); |
|
||||
} |
|
||||
} |
|
||||
$this -> parseException($model, $request, $exception, $message); |
|
||||
}); |
|
||||
$promise -> wait(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
protected function doRequestAsync($model, &$operation, $params, $callback, $startAsync, $originMethod, $endpoint = null){ |
|
||||
$request = $this -> makeRequest($model, $operation, $params, $endpoint); |
|
||||
return $this->sendRequestAsync($model, $operation, $params, $callback, $startAsync, $originMethod, $request); |
|
||||
} |
|
||||
|
|
||||
protected function sendRequestAsync($model, &$operation, $params, $callback, $startAsync, $originMethod, $request, $requestCount = 1) |
|
||||
{ |
|
||||
$start = microtime(true); |
|
||||
|
|
||||
$saveAsStream = false; |
|
||||
if(isset($operation['stream']) && $operation['stream']){ |
|
||||
$saveAsStream = isset($params['SaveAsStream']) ? $params['SaveAsStream'] : false; |
|
||||
|
|
||||
if($saveAsStream){ |
|
||||
if(isset($params['SaveAsFile'])){ |
|
||||
$obsException = new ObsException('SaveAsStream cannot be used with SaveAsFile together'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
if(isset($params['FilePath'])){ |
|
||||
$obsException = new ObsException('SaveAsStream cannot be used with FilePath together'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if(isset($params['SaveAsFile']) && isset($params['FilePath'])){ |
|
||||
$obsException = new ObsException('SaveAsFile cannot be used with FilePath together'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
} |
|
||||
return $this->httpClient->sendAsync($request, ['stream' => $saveAsStream])->then( |
|
||||
function(Response $response) use ($model, $operation, $params, $callback, $startAsync, $originMethod, $request, $start){ |
|
||||
ObsLog::commonLog(INFO, 'http request cost ' . round(microtime(true) - $start, 3) * 1000 . ' ms'); |
|
||||
$statusCode = $response -> getStatusCode(); |
|
||||
$readable = isset($params['Body']) && ($params['Body'] instanceof StreamInterface || is_resource($params['Body'])); |
|
||||
if($statusCode === 307 && !$readable){ |
|
||||
if($location = $response -> getHeaderLine('location')){ |
|
||||
$url = parse_url($this->endpoint); |
|
||||
$newUrl = parse_url($location); |
|
||||
$scheme = (isset($newUrl['scheme']) ? $newUrl['scheme'] : $url['scheme']); |
|
||||
$defaultPort = strtolower($scheme) === 'https' ? '443' : '80'; |
|
||||
return $this->doRequestAsync($model, $operation, $params, $callback, $startAsync, $originMethod, $scheme. '://' . $newUrl['host'] . |
|
||||
':' . (isset($newUrl['port']) ? $newUrl['port'] : $defaultPort)); |
|
||||
} |
|
||||
} |
|
||||
$this -> parseResponse($model, $request, $response, $operation); |
|
||||
ObsLog::commonLog(INFO, 'obsclient cost ' . round(microtime(true) - $startAsync, 3) * 1000 . ' ms to execute '. $originMethod); |
|
||||
unset($model['method']); |
|
||||
$callback(null, $model); |
|
||||
}, |
|
||||
function (RequestException $exception) use ($model, $operation, $params, $callback, $startAsync, $originMethod, $request, $start, $requestCount){ |
|
||||
ObsLog::commonLog(INFO, 'http request cost ' . round(microtime(true) - $start, 3) * 1000 . ' ms'); |
|
||||
$message = null; |
|
||||
if($exception instanceof ConnectException){ |
|
||||
if($requestCount <= $this->maxRetryCount){ |
|
||||
return $this -> sendRequestAsync($model, $operation, $params, $callback, $startAsync, $originMethod, $request, $requestCount + 1); |
|
||||
}else{ |
|
||||
$message = 'Exceeded retry limitation, max retry count:'. $this->maxRetryCount . ', error message:' . $exception -> getMessage(); |
|
||||
} |
|
||||
} |
|
||||
$obsException = $this -> parseExceptionAsync($request, $exception, $message); |
|
||||
ObsLog::commonLog(INFO, 'obsclient cost ' . round(microtime(true) - $startAsync, 3) * 1000 . ' ms to execute '. $originMethod); |
|
||||
$callback($obsException, null); |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
@ -1,471 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Signature; |
|
||||
|
|
||||
use Obs\Log\ObsLog; |
|
||||
use Obs\Internal\Resource\Constants; |
|
||||
use Obs\ObsException; |
|
||||
use Obs\Internal\Common\SchemaFormatter; |
|
||||
use GuzzleHttp\Psr7\Stream; |
|
||||
use Obs\Internal\Common\Model; |
|
||||
use Psr\Http\Message\StreamInterface; |
|
||||
use Obs\Internal\Common\ObsTransform; |
|
||||
use Obs\Internal\Common\V2Transform; |
|
||||
|
|
||||
abstract class AbstractSignature implements SignatureInterface |
|
||||
{ |
|
||||
|
|
||||
protected $ak; |
|
||||
|
|
||||
protected $sk; |
|
||||
|
|
||||
protected $pathStyle; |
|
||||
|
|
||||
protected $endpoint; |
|
||||
|
|
||||
protected $methodName; |
|
||||
|
|
||||
protected $securityToken; |
|
||||
|
|
||||
protected $signature; |
|
||||
|
|
||||
protected $isCname; |
|
||||
|
|
||||
public static function urlencodeWithSafe($val, $safe='/'){ |
|
||||
if(($len = strlen($val)) === 0){ |
|
||||
return ''; |
|
||||
} |
|
||||
$buffer = []; |
|
||||
for ($index=0;$index<$len;$index++){ |
|
||||
$str = $val[$index]; |
|
||||
$buffer[] = !($pos = strpos($safe, $str)) && $pos !== 0 ? rawurlencode($str) : $str; |
|
||||
} |
|
||||
return implode('', $buffer); |
|
||||
} |
|
||||
|
|
||||
protected function __construct($ak, $sk, $pathStyle, $endpoint, $methodName, $signature, $securityToken=false, $isCname=false) |
|
||||
{ |
|
||||
$this -> ak = $ak; |
|
||||
$this -> sk = $sk; |
|
||||
$this -> pathStyle = $pathStyle; |
|
||||
$this -> endpoint = $endpoint; |
|
||||
$this -> methodName = $methodName; |
|
||||
$this -> signature = $signature; |
|
||||
$this -> securityToken = $securityToken; |
|
||||
$this -> isCname = $isCname; |
|
||||
} |
|
||||
|
|
||||
protected function transXmlByType($key, &$value, &$subParams, $transHolder) |
|
||||
{ |
|
||||
$xml = []; |
|
||||
$treatAsString = false; |
|
||||
if(isset($value['type'])){ |
|
||||
$type = $value['type']; |
|
||||
if($type === 'array'){ |
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : $key; |
|
||||
$subXml = []; |
|
||||
foreach($subParams as $item){ |
|
||||
$temp = $this->transXmlByType($key, $value['items'], $item, $transHolder); |
|
||||
if($temp !== ''){ |
|
||||
$subXml[] = $temp; |
|
||||
} |
|
||||
} |
|
||||
if(!empty($subXml)){ |
|
||||
if(!isset($value['data']['xmlFlattened'])){ |
|
||||
$xml[] = '<' . $name . '>'; |
|
||||
$xml[] = implode('', $subXml); |
|
||||
$xml[] = '</' . $name . '>'; |
|
||||
}else{ |
|
||||
$xml[] = implode('', $subXml); |
|
||||
} |
|
||||
} |
|
||||
}else if($type === 'object'){ |
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : (isset($value['name']) ? $value['name'] : $key); |
|
||||
$properties = $value['properties']; |
|
||||
$subXml = []; |
|
||||
$attr = []; |
|
||||
foreach ($properties as $pkey => $pvalue){ |
|
||||
if(isset($pvalue['required']) && $pvalue['required'] && !isset($subParams[$pkey])){ |
|
||||
$obsException= new ObsException('param:' .$pkey. ' is required'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
if(isset($subParams[$pkey])){ |
|
||||
if(isset($pvalue['data']) && isset($pvalue['data']['xmlAttribute']) && $pvalue['data']['xmlAttribute']){ |
|
||||
$attrValue = $this->xml_tansfer(trim(strval($subParams[$pkey]))); |
|
||||
$attr[$pvalue['sentAs']] = '"' . $attrValue . '"'; |
|
||||
if(isset($pvalue['data']['xmlNamespace'])){ |
|
||||
$ns = substr($pvalue['sentAs'], 0, strpos($pvalue['sentAs'], ':')); |
|
||||
$attr['xmlns:' . $ns] = '"' . $pvalue['data']['xmlNamespace'] . '"'; |
|
||||
} |
|
||||
}else{ |
|
||||
$subXml[] = $this -> transXmlByType($pkey, $pvalue, $subParams[$pkey], $transHolder); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
$val = implode('', $subXml); |
|
||||
if($val !== ''){ |
|
||||
$_name = $name; |
|
||||
if(!empty($attr)){ |
|
||||
foreach ($attr as $akey => $avalue){ |
|
||||
$_name .= ' ' . $akey . '=' . $avalue; |
|
||||
} |
|
||||
} |
|
||||
if(!isset($value['data']['xmlFlattened'])){ |
|
||||
$xml[] = '<' . $_name . '>'; |
|
||||
$xml[] = $val; |
|
||||
$xml[] = '</' . $name . '>'; |
|
||||
} else { |
|
||||
$xml[] = $val; |
|
||||
} |
|
||||
} |
|
||||
}else{ |
|
||||
$treatAsString = true; |
|
||||
} |
|
||||
}else{ |
|
||||
$treatAsString = true; |
|
||||
$type = null; |
|
||||
} |
|
||||
|
|
||||
if($treatAsString){ |
|
||||
if($type === 'boolean'){ |
|
||||
if(!is_bool($subParams) && strval($subParams) !== 'false' && strval($subParams) !== 'true'){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a boolean value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
}else if($type === 'numeric'){ |
|
||||
if(!is_numeric($subParams)){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a numeric value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
}else if($type === 'float'){ |
|
||||
if(!is_float($subParams)){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a float value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
}else if($type === 'int' || $type === 'integer'){ |
|
||||
if(!is_int($subParams)){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a int value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : $key; |
|
||||
if(is_bool($subParams)){ |
|
||||
$val = $subParams ? 'true' : 'false'; |
|
||||
}else{ |
|
||||
$val = strval($subParams); |
|
||||
} |
|
||||
if(isset($value['format'])){ |
|
||||
$val = SchemaFormatter::format($value['format'], $val); |
|
||||
} |
|
||||
if (isset($value['transform'])) { |
|
||||
$val = $transHolder->transform($value['transform'], $val); |
|
||||
} |
|
||||
if(isset($val) && $val !== ''){ |
|
||||
$val = $this->xml_tansfer($val); |
|
||||
if(!isset($value['data']['xmlFlattened'])){ |
|
||||
$xml[] = '<' . $name . '>'; |
|
||||
$xml[] = $val; |
|
||||
$xml[] = '</' . $name . '>'; |
|
||||
} else { |
|
||||
$xml[] = $val; |
|
||||
} |
|
||||
}else if(isset($value['canEmpty']) && $value['canEmpty']){ |
|
||||
$xml[] = '<' . $name . '>'; |
|
||||
$xml[] = $val; |
|
||||
$xml[] = '</' . $name . '>'; |
|
||||
} |
|
||||
} |
|
||||
$ret = implode('', $xml); |
|
||||
|
|
||||
if(isset($value['wrapper'])){ |
|
||||
$ret = '<'. $value['wrapper'] . '>' . $ret . '</'. $value['wrapper'] . '>'; |
|
||||
} |
|
||||
|
|
||||
return $ret; |
|
||||
} |
|
||||
|
|
||||
private function xml_tansfer($tag) { |
|
||||
$search = array('&', '<', '>', '\'', '"'); |
|
||||
$repalce = array('&', '<', '>', ''', '"'); |
|
||||
$transferXml = str_replace($search, $repalce, $tag); |
|
||||
return $transferXml; |
|
||||
} |
|
||||
|
|
||||
protected function prepareAuth(array &$requestConfig, array &$params, Model $model) |
|
||||
{ |
|
||||
$transHolder = strcasecmp($this-> signature, 'obs') === 0 ? ObsTransform::getInstance() : V2Transform::getInstance(); |
|
||||
$method = $requestConfig['httpMethod']; |
|
||||
$requestUrl = $this->endpoint; |
|
||||
$headers = []; |
|
||||
$pathArgs = []; |
|
||||
$dnsParam = null; |
|
||||
$uriParam = null; |
|
||||
$body = []; |
|
||||
$xml = []; |
|
||||
|
|
||||
if(isset($requestConfig['specialParam'])){ |
|
||||
$pathArgs[$requestConfig['specialParam']] = ''; |
|
||||
} |
|
||||
|
|
||||
$result = ['body' => null]; |
|
||||
$url = parse_url($requestUrl); |
|
||||
$host = $url['host']; |
|
||||
|
|
||||
$fileFlag = false; |
|
||||
|
|
||||
if(isset($requestConfig['requestParameters'])){ |
|
||||
$paramsMetadata = $requestConfig['requestParameters']; |
|
||||
foreach ($paramsMetadata as $key => $value){ |
|
||||
if(isset($value['required']) && $value['required'] && !isset($params[$key])){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is required'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
if(isset($params[$key]) && isset($value['location'])){ |
|
||||
$location = $value['location']; |
|
||||
$val = $params[$key]; |
|
||||
$type = 'string'; |
|
||||
if($val !== '' && isset($value['type'])){ |
|
||||
$type = $value['type']; |
|
||||
if($type === 'boolean'){ |
|
||||
if(!is_bool($val) && strval($val) !== 'false' && strval($val) !== 'true'){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a boolean value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
}else if($type === 'numeric'){ |
|
||||
if(!is_numeric($val)){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a numeric value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
}else if($type === 'float'){ |
|
||||
if(!is_float($val)){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a float value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
}else if($type === 'int' || $type === 'integer'){ |
|
||||
if(!is_int($val)){ |
|
||||
$obsException= new ObsException('param:' .$key. ' is not a int value'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($location === 'header'){ |
|
||||
if($type === 'object'){ |
|
||||
if(is_array($val)){ |
|
||||
$sentAs = strtolower($value['sentAs']); |
|
||||
foreach ($val as $k => $v){ |
|
||||
$k = self::urlencodeWithSafe(strtolower($k), ' ;/?:@&=+$,'); |
|
||||
$name = strpos($k, $sentAs) === 0 ? $k : $sentAs . $k; |
|
||||
$headers[$name] = self::urlencodeWithSafe($v, ' ;/?:@&=+$,\'*'); |
|
||||
} |
|
||||
} |
|
||||
}else if($type === 'array'){ |
|
||||
if(is_array($val)){ |
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : (isset($value['items']['sentAs']) ? $value['items']['sentAs'] : $key); |
|
||||
$temp = []; |
|
||||
foreach ($val as $v){ |
|
||||
if(($v = strval($v)) !== ''){ |
|
||||
$temp[] = self::urlencodeWithSafe($val, ' ;/?:@&=+$,\'*'); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$headers[$name] = $temp; |
|
||||
} |
|
||||
}else if($type === 'password'){ |
|
||||
if(($val = strval($val)) !== ''){ |
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : $key; |
|
||||
$pwdName = isset($value['pwdSentAs']) ? $value['pwdSentAs'] : $name . '-MD5'; |
|
||||
$val1 = base64_encode($val); |
|
||||
$val2 = base64_encode(md5($val, true)); |
|
||||
$headers[$name] = $val1; |
|
||||
$headers[$pwdName] = $val2; |
|
||||
} |
|
||||
}else{ |
|
||||
if (isset($value['transform'])) { |
|
||||
$val = $transHolder->transform($value['transform'], strval($val)); |
|
||||
} |
|
||||
if(isset($val)){ |
|
||||
if(is_bool($val)){ |
|
||||
$val = $val ? 'true' : 'false'; |
|
||||
}else{ |
|
||||
$val = strval($val); |
|
||||
} |
|
||||
if($val !== ''){ |
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : $key; |
|
||||
if(isset($value['format'])){ |
|
||||
$val = SchemaFormatter::format($value['format'], $val); |
|
||||
} |
|
||||
$headers[$name] = self::urlencodeWithSafe($val, ' ;/?:@&=+$,\'*'); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}else if($location === 'uri' && $uriParam === null){ |
|
||||
$uriParam = self::urlencodeWithSafe($val); |
|
||||
}else if($location === 'dns' && $dnsParam === null){ |
|
||||
$dnsParam = $val; |
|
||||
}else if($location === 'query'){ |
|
||||
$name = isset($value['sentAs']) ? $value['sentAs'] : $key; |
|
||||
if(strval($val) !== ''){ |
|
||||
if (strcasecmp ( $this->signature, 'v4' ) === 0) { |
|
||||
$pathArgs[rawurlencode($name)] = rawurlencode(strval($val)); |
|
||||
} else { |
|
||||
$pathArgs[self::urlencodeWithSafe($name)] = self::urlencodeWithSafe(strval($val)); |
|
||||
} |
|
||||
} |
|
||||
}else if($location === 'xml'){ |
|
||||
$val = $this->transXmlByType($key, $value, $val, $transHolder); |
|
||||
if($val !== ''){ |
|
||||
$xml[] = $val; |
|
||||
} |
|
||||
}else if($location === 'body'){ |
|
||||
|
|
||||
if(isset($result['body'])){ |
|
||||
$obsException= new ObsException('duplicated body provided'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
|
|
||||
if($type === 'file'){ |
|
||||
if(!file_exists($val)){ |
|
||||
$obsException= new ObsException('file[' .$val. '] does not exist'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
$result['body'] = new Stream(fopen($val, 'r')); |
|
||||
$fileFlag = true; |
|
||||
}else if($type === 'stream'){ |
|
||||
$result['body'] = $val; |
|
||||
} else if ($type === 'json') { |
|
||||
//TODO |
|
||||
$jsonData = json_encode($val); |
|
||||
if (!$jsonData) { |
|
||||
$obsException= new ObsException('input is invalid, since it is not json data'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
$result['body'] = strval($jsonData); |
|
||||
} else{ |
|
||||
$result['body'] = strval($val); |
|
||||
} |
|
||||
}else if($location === 'response'){ |
|
||||
$model[$key] = ['value' => $val, 'type' => $type]; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
if($dnsParam){ |
|
||||
if($this -> pathStyle){ |
|
||||
$requestUrl = $requestUrl . '/' . $dnsParam; |
|
||||
}else{ |
|
||||
$defaultPort = strtolower($url['scheme']) === 'https' ? '443' : '80'; |
|
||||
$host = $this -> isCname ? $host : $dnsParam. '.' . $host; |
|
||||
$requestUrl = $url['scheme'] . '://' . $host . ':' . (isset($url['port']) ? $url['port'] : $defaultPort); |
|
||||
} |
|
||||
} |
|
||||
if($uriParam){ |
|
||||
$requestUrl = $requestUrl . '/' . $uriParam; |
|
||||
} |
|
||||
|
|
||||
if(!empty($pathArgs)){ |
|
||||
$requestUrl .= '?'; |
|
||||
$_pathArgs = []; |
|
||||
foreach ($pathArgs as $key => $value){ |
|
||||
$_pathArgs[] = $value === null || $value === '' ? $key : $key . '=' . $value; |
|
||||
} |
|
||||
$requestUrl .= implode('&', $_pathArgs); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($xml || (isset($requestConfig['data']['xmlAllowEmpty']) && $requestConfig['data']['xmlAllowEmpty'])){ |
|
||||
$body[] = '<'; |
|
||||
$xmlRoot = $requestConfig['data']['xmlRoot']['name']; |
|
||||
|
|
||||
$body[] = $xmlRoot; |
|
||||
$body[] = '>'; |
|
||||
$body[] = implode('', $xml); |
|
||||
$body[] = '</'; |
|
||||
$body[] = $xmlRoot; |
|
||||
$body[] = '>'; |
|
||||
$headers['Content-Type'] = 'application/xml'; |
|
||||
$result['body'] = implode('', $body); |
|
||||
|
|
||||
ObsLog::commonLog(DEBUG, 'request content ' . $result['body']); |
|
||||
|
|
||||
if(isset($requestConfig['data']['contentMd5']) && $requestConfig['data']['contentMd5']){ |
|
||||
$headers['Content-MD5'] = base64_encode(md5($result['body'],true)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($fileFlag && ($result['body'] instanceof StreamInterface)){ |
|
||||
if($this->methodName === 'uploadPart' && (isset($model['Offset']) || isset($model['PartSize']))){ |
|
||||
$bodySize = $result['body'] ->getSize(); |
|
||||
if(isset($model['Offset'])){ |
|
||||
$offset = intval($model['Offset']['value']); |
|
||||
$offset = $offset >= 0 && $offset < $bodySize ? $offset : 0; |
|
||||
}else{ |
|
||||
$offset = 0; |
|
||||
} |
|
||||
|
|
||||
if(isset($model['PartSize'])){ |
|
||||
$partSize = intval($model['PartSize']['value']); |
|
||||
$partSize = $partSize > 0 && $partSize <= ($bodySize - $offset) ? $partSize : $bodySize - $offset; |
|
||||
}else{ |
|
||||
$partSize = $bodySize - $offset; |
|
||||
} |
|
||||
$result['body'] -> rewind(); |
|
||||
$result['body'] -> seek($offset); |
|
||||
$headers['Content-Length'] = $partSize; |
|
||||
}else if(isset($headers['Content-Length'])){ |
|
||||
$bodySize = $result['body'] -> getSize(); |
|
||||
if(intval($headers['Content-Length']) > $bodySize){ |
|
||||
$headers['Content-Length'] = $bodySize; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$constants = Constants::selectConstants($this -> signature); |
|
||||
|
|
||||
if($this->securityToken){ |
|
||||
$headers[$constants::SECURITY_TOKEN_HEAD] = $this->securityToken; |
|
||||
} |
|
||||
|
|
||||
$headers['Host'] = $host; |
|
||||
|
|
||||
$result['host'] = $host; |
|
||||
$result['method'] = $method; |
|
||||
$result['headers'] = $headers; |
|
||||
$result['pathArgs'] = $pathArgs; |
|
||||
$result['dnsParam'] = $dnsParam; |
|
||||
$result['uriParam'] = $uriParam; |
|
||||
$result['requestUrl'] = $requestUrl; |
|
||||
|
|
||||
return $result; |
|
||||
} |
|
||||
} |
|
||||
@ -1,138 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Signature; |
|
||||
|
|
||||
|
|
||||
use Obs\Internal\Resource\Constants; |
|
||||
use Obs\Internal\Common\Model; |
|
||||
use Obs\Internal\Resource\V2Constants; |
|
||||
|
|
||||
class DefaultSignature extends AbstractSignature |
|
||||
{ |
|
||||
const INTEREST_HEADER_KEY_LIST = array('content-type', 'content-md5', 'date'); |
|
||||
|
|
||||
|
|
||||
public function __construct($ak, $sk, $pathStyle, $endpoint, $methodName, $signature, $securityToken=false, $isCname=false) |
|
||||
{ |
|
||||
|
|
||||
parent::__construct($ak, $sk, $pathStyle, $endpoint, $methodName, $signature, $securityToken, $isCname); |
|
||||
} |
|
||||
|
|
||||
public function doAuth(array &$requestConfig, array &$params, Model $model) |
|
||||
{ |
|
||||
$result = $this -> prepareAuth($requestConfig, $params, $model); |
|
||||
|
|
||||
$result['headers']['Date'] = gmdate('D, d M Y H:i:s \G\M\T'); |
|
||||
$canonicalstring = $this-> makeCanonicalstring($result['method'], $result['headers'], $result['pathArgs'], $result['dnsParam'], $result['uriParam']); |
|
||||
|
|
||||
$result['cannonicalRequest'] = $canonicalstring; |
|
||||
|
|
||||
$signature = base64_encode(hash_hmac('sha1', $canonicalstring, $this->sk, true)); |
|
||||
|
|
||||
$constants = Constants::selectConstants($this -> signature); |
|
||||
$signatureFlag = $constants::FLAG; |
|
||||
|
|
||||
$authorization = $signatureFlag . ' ' . $this->ak . ':' . $signature; |
|
||||
|
|
||||
$result['headers']['Authorization'] = $authorization; |
|
||||
|
|
||||
return $result; |
|
||||
} |
|
||||
|
|
||||
public function makeCanonicalstring($method, $headers, $pathArgs, $bucketName, $objectKey, $expires = null) |
|
||||
{ |
|
||||
$buffer = []; |
|
||||
$buffer[] = $method; |
|
||||
$buffer[] = "\n"; |
|
||||
$interestHeaders = []; |
|
||||
$constants = Constants::selectConstants($this -> signature); |
|
||||
|
|
||||
foreach ($headers as $key => $value){ |
|
||||
$key = strtolower($key); |
|
||||
if(in_array($key, self::INTEREST_HEADER_KEY_LIST) || strpos($key, $constants::HEADER_PREFIX) === 0){ |
|
||||
$interestHeaders[$key] = $value; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if(array_key_exists($constants::ALTERNATIVE_DATE_HEADER, $interestHeaders)){ |
|
||||
$interestHeaders['date'] = ''; |
|
||||
} |
|
||||
|
|
||||
if($expires !== null){ |
|
||||
$interestHeaders['date'] = strval($expires); |
|
||||
} |
|
||||
|
|
||||
if(!array_key_exists('content-type', $interestHeaders)){ |
|
||||
$interestHeaders['content-type'] = ''; |
|
||||
} |
|
||||
|
|
||||
if(!array_key_exists('content-md5', $interestHeaders)){ |
|
||||
$interestHeaders['content-md5'] = ''; |
|
||||
} |
|
||||
|
|
||||
ksort($interestHeaders); |
|
||||
|
|
||||
foreach ($interestHeaders as $key => $value){ |
|
||||
if(strpos($key, $constants::HEADER_PREFIX) === 0){ |
|
||||
$buffer[] = $key . ':' . $value; |
|
||||
}else{ |
|
||||
$buffer[] = $value; |
|
||||
} |
|
||||
$buffer[] = "\n"; |
|
||||
} |
|
||||
|
|
||||
$uri = ''; |
|
||||
|
|
||||
$bucketName = $this->isCname ? $headers['Host'] : $bucketName; |
|
||||
|
|
||||
if($bucketName){ |
|
||||
$uri .= '/'; |
|
||||
$uri .= $bucketName; |
|
||||
if(!$this->pathStyle){ |
|
||||
$uri .= '/'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($objectKey){ |
|
||||
if(!($pos=strripos($uri, '/')) || strlen($uri)-1 !== $pos){ |
|
||||
$uri .= '/'; |
|
||||
} |
|
||||
$uri .= $objectKey; |
|
||||
} |
|
||||
|
|
||||
$buffer[] = $uri === ''? '/' : $uri; |
|
||||
|
|
||||
|
|
||||
if(!empty($pathArgs)){ |
|
||||
ksort($pathArgs); |
|
||||
$_pathArgs = []; |
|
||||
foreach ($pathArgs as $key => $value){ |
|
||||
if(in_array(strtolower($key), $constants::ALLOWED_RESOURCE_PARAMTER_NAMES) || strpos($key, $constants::HEADER_PREFIX) === 0){ |
|
||||
$_pathArgs[] = $value === null || $value === '' ? $key : $key . '=' . urldecode($value); |
|
||||
} |
|
||||
} |
|
||||
if(!empty($_pathArgs)){ |
|
||||
$buffer[] = '?'; |
|
||||
$buffer[] = implode('&', $_pathArgs); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return implode('', $buffer); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,25 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Signature; |
|
||||
|
|
||||
use Obs\Internal\Common\Model; |
|
||||
|
|
||||
interface SignatureInterface |
|
||||
{ |
|
||||
function doAuth(array &$requestConfig, array &$params, Model $model); |
|
||||
} |
|
||||
@ -1,199 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Internal\Signature; |
|
||||
|
|
||||
use Obs\Internal\Common\Model; |
|
||||
|
|
||||
class V4Signature extends AbstractSignature |
|
||||
{ |
|
||||
const CONTENT_SHA256 = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'; |
|
||||
|
|
||||
protected $region; |
|
||||
|
|
||||
protected $utcTimeZone; |
|
||||
|
|
||||
public function __construct($ak, $sk, $pathStyle, $endpoint, $region, $methodName, $signature, $securityToken=false, $isCname=false) |
|
||||
{ |
|
||||
parent::__construct($ak, $sk, $pathStyle, $endpoint, $methodName, $signature, $securityToken, $isCname); |
|
||||
$this->region = $region; |
|
||||
$this->utcTimeZone = new \DateTimeZone ('UTC'); |
|
||||
} |
|
||||
|
|
||||
public function doAuth(array &$requestConfig, array &$params, Model $model) |
|
||||
{ |
|
||||
$result = $this -> prepareAuth($requestConfig, $params, $model); |
|
||||
|
|
||||
$result['headers']['x-amz-content-sha256'] = self::CONTENT_SHA256; |
|
||||
|
|
||||
$bucketName = $result['dnsParam']; |
|
||||
|
|
||||
$result['headers']['Host'] = $result['host']; |
|
||||
|
|
||||
$time = null; |
|
||||
if(array_key_exists('x-amz-date', $result['headers'])){ |
|
||||
$time = $result['headers']['x-amz-date']; |
|
||||
}else if(array_key_exists('X-Amz-Date', $result['headers'])){ |
|
||||
$time = $result['headers']['X-Amz-Date']; |
|
||||
} |
|
||||
$timestamp = $time ? date_create_from_format('Ymd\THis\Z', $time, $this->utcTimeZone) -> getTimestamp() |
|
||||
:time(); |
|
||||
|
|
||||
$result['headers']['Date'] = gmdate('D, d M Y H:i:s \G\M\T', $timestamp); |
|
||||
|
|
||||
$longDate = gmdate('Ymd\THis\Z', $timestamp); |
|
||||
$shortDate = substr($longDate, 0, 8); |
|
||||
|
|
||||
$credential = $this-> getCredential($shortDate); |
|
||||
|
|
||||
$signedHeaders = $this->getSignedHeaders($result['headers']); |
|
||||
|
|
||||
$canonicalstring = $this-> makeCanonicalstring($result['method'], $result['headers'], $result['pathArgs'], $bucketName, $result['uriParam'], $signedHeaders); |
|
||||
|
|
||||
$result['cannonicalRequest'] = $canonicalstring; |
|
||||
|
|
||||
$signature = $this -> getSignature($canonicalstring, $longDate, $shortDate); |
|
||||
|
|
||||
$authorization = 'AWS4-HMAC-SHA256 ' . 'Credential=' . $credential. ',' . 'SignedHeaders=' . $signedHeaders . ',' . 'Signature=' . $signature; |
|
||||
|
|
||||
$result['headers']['Authorization'] = $authorization; |
|
||||
|
|
||||
return $result; |
|
||||
} |
|
||||
|
|
||||
public function getSignature($canonicalstring, $longDate, $shortDate) |
|
||||
{ |
|
||||
$stringToSign = []; |
|
||||
$stringToSign[] = 'AWS4-HMAC-SHA256'; |
|
||||
|
|
||||
$stringToSign[] = "\n"; |
|
||||
|
|
||||
$stringToSign[] = $longDate; |
|
||||
|
|
||||
$stringToSign[] = "\n"; |
|
||||
$stringToSign[] = $this -> getScope($shortDate); |
|
||||
$stringToSign[] = "\n"; |
|
||||
|
|
||||
$stringToSign[] = hash('sha256', $canonicalstring); |
|
||||
|
|
||||
$dateKey = hash_hmac('sha256', $shortDate, 'AWS4' . $this -> sk, true); |
|
||||
$regionKey = hash_hmac('sha256', $this->region, $dateKey, true); |
|
||||
$serviceKey = hash_hmac('sha256', 's3', $regionKey, true); |
|
||||
$signingKey = hash_hmac('sha256', 'aws4_request', $serviceKey, true); |
|
||||
$signature = hash_hmac('sha256', implode('', $stringToSign), $signingKey); |
|
||||
return $signature; |
|
||||
} |
|
||||
|
|
||||
public function getCanonicalQueryString($pathArgs) |
|
||||
{ |
|
||||
$queryStr = ''; |
|
||||
|
|
||||
ksort($pathArgs); |
|
||||
$index = 0; |
|
||||
foreach ($pathArgs as $key => $value){ |
|
||||
$queryStr .= $key . '=' . $value; |
|
||||
if($index++ !== count($pathArgs) - 1){ |
|
||||
$queryStr .= '&'; |
|
||||
} |
|
||||
} |
|
||||
return $queryStr; |
|
||||
} |
|
||||
|
|
||||
public function getCanonicalHeaders($headers) |
|
||||
{ |
|
||||
$_headers = []; |
|
||||
foreach ($headers as $key => $value) { |
|
||||
$_headers[strtolower($key)] = $value; |
|
||||
} |
|
||||
ksort($_headers); |
|
||||
|
|
||||
$canonicalHeaderStr = ''; |
|
||||
|
|
||||
foreach ($_headers as $key => $value){ |
|
||||
$value = is_array($value) ? implode(',', $value) : $value; |
|
||||
$canonicalHeaderStr .= $key . ':' . $value; |
|
||||
$canonicalHeaderStr .= "\n"; |
|
||||
} |
|
||||
return $canonicalHeaderStr; |
|
||||
} |
|
||||
|
|
||||
public function getCanonicalURI($bucketName, $objectKey) |
|
||||
{ |
|
||||
$uri = ''; |
|
||||
if($this -> pathStyle && $bucketName){ |
|
||||
$uri .= '/' . $bucketName; |
|
||||
} |
|
||||
|
|
||||
if($objectKey){ |
|
||||
$uri .= '/' . $objectKey; |
|
||||
} |
|
||||
|
|
||||
if($uri === ''){ |
|
||||
$uri = '/'; |
|
||||
} |
|
||||
return $uri; |
|
||||
} |
|
||||
|
|
||||
public function makeCanonicalstring($method, $headers, $pathArgs, $bucketName, $objectKey, $signedHeaders=null, $payload=null) |
|
||||
{ |
|
||||
$buffer = []; |
|
||||
$buffer[] = $method; |
|
||||
$buffer[] = "\n"; |
|
||||
$buffer[] = $this->getCanonicalURI($bucketName, $objectKey); |
|
||||
$buffer[] = "\n"; |
|
||||
$buffer[] = $this->getCanonicalQueryString($pathArgs); |
|
||||
$buffer[] = "\n"; |
|
||||
$buffer[] = $this->getCanonicalHeaders($headers); |
|
||||
$buffer[] = "\n"; |
|
||||
$buffer[] = $signedHeaders ? $signedHeaders : $this->getSignedHeaders($headers); |
|
||||
$buffer[] = "\n"; |
|
||||
$buffer[] = $payload ? strval($payload) : self::CONTENT_SHA256; |
|
||||
|
|
||||
return implode('', $buffer); |
|
||||
} |
|
||||
|
|
||||
public function getSignedHeaders($headers) |
|
||||
{ |
|
||||
$_headers = []; |
|
||||
|
|
||||
foreach ($headers as $key => $value) { |
|
||||
$_headers[] = strtolower($key); |
|
||||
} |
|
||||
|
|
||||
sort($_headers); |
|
||||
|
|
||||
$signedHeaders = ''; |
|
||||
|
|
||||
foreach ($_headers as $key => $value){ |
|
||||
$signedHeaders .= $value; |
|
||||
if($key !== count($_headers) - 1){ |
|
||||
$signedHeaders .= ';'; |
|
||||
} |
|
||||
} |
|
||||
return $signedHeaders; |
|
||||
} |
|
||||
|
|
||||
public function getScope($shortDate) |
|
||||
{ |
|
||||
return $shortDate . '/' . $this->region . '/s3/aws4_request'; |
|
||||
} |
|
||||
|
|
||||
public function getCredential($shortDate) |
|
||||
{ |
|
||||
return $this->ak . '/' . $this->getScope($shortDate); |
|
||||
} |
|
||||
} |
|
||||
@ -1,28 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Log; |
|
||||
|
|
||||
class ObsConfig |
|
||||
{ |
|
||||
const LOG_FILE_CONFIG = [ |
|
||||
'FilePath'=>'./logs', |
|
||||
'FileName'=>'eSDK-OBS-PHP.log', |
|
||||
'MaxFiles'=>10, |
|
||||
'Level'=>INFO |
|
||||
]; |
|
||||
} |
|
||||
@ -1,126 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs\Log; |
|
||||
|
|
||||
use Monolog\Formatter\LineFormatter; |
|
||||
use Monolog\Handler\RotatingFileHandler; |
|
||||
use Monolog\Logger; |
|
||||
|
|
||||
class ObsLog extends Logger |
|
||||
{ |
|
||||
public static $log = null; |
|
||||
|
|
||||
protected $log_path = './'; |
|
||||
protected $log_name = null; |
|
||||
protected $log_level = Logger::DEBUG; |
|
||||
protected $log_maxFiles = 0; |
|
||||
|
|
||||
private $formatter = null; |
|
||||
private $handler = null; |
|
||||
private $filepath = ''; |
|
||||
|
|
||||
public static function initLog($logConfig= []) |
|
||||
{ |
|
||||
$s3log = new ObsLog(''); |
|
||||
$s3log->setConfig($logConfig); |
|
||||
$s3log->cheakDir(); |
|
||||
$s3log->setFilePath(); |
|
||||
$s3log->setFormat(); |
|
||||
$s3log->setHande(); |
|
||||
} |
|
||||
private function setFormat() |
|
||||
{ |
|
||||
$output = '[%datetime%][%level_name%]'.'%message%' . "\n"; |
|
||||
$this->formatter = new LineFormatter($output); |
|
||||
|
|
||||
} |
|
||||
private function setHande() |
|
||||
{ |
|
||||
self::$log = new Logger('obs_logger'); |
|
||||
$rotating = new RotatingFileHandler($this->filepath, $this->log_maxFiles, $this->log_level); |
|
||||
$rotating->setFormatter($this->formatter); |
|
||||
self::$log->pushHandler($rotating); |
|
||||
} |
|
||||
private function setConfig($logConfig= []) |
|
||||
{ |
|
||||
$arr = empty($logConfig) ? ObsConfig::LOG_FILE_CONFIG : $logConfig; |
|
||||
$this->log_path = iconv('UTF-8', 'GBK',$arr['FilePath']); |
|
||||
$this->log_name = iconv('UTF-8', 'GBK',$arr['FileName']); |
|
||||
$this->log_maxFiles = is_numeric($arr['MaxFiles']) ? 0 : intval($arr['MaxFiles']); |
|
||||
$this->log_level = $arr['Level']; |
|
||||
} |
|
||||
private function cheakDir() |
|
||||
{ |
|
||||
if (!is_dir($this->log_path)){ |
|
||||
mkdir($this->log_path, 0755, true); |
|
||||
} |
|
||||
} |
|
||||
private function setFilePath() |
|
||||
{ |
|
||||
$this->filepath = $this->log_path.'/'.$this->log_name; |
|
||||
} |
|
||||
private static function writeLog($level, $msg) |
|
||||
{ |
|
||||
switch ($level) { |
|
||||
case DEBUG: |
|
||||
self::$log->debug($msg); |
|
||||
break; |
|
||||
case INFO: |
|
||||
self::$log->info($msg); |
|
||||
break; |
|
||||
case NOTICE: |
|
||||
self::$log->notice($msg); |
|
||||
break; |
|
||||
case WARNING: |
|
||||
self::$log->warning($msg); |
|
||||
break; |
|
||||
case ERROR: |
|
||||
self::$log->error($msg); |
|
||||
break; |
|
||||
case CRITICAL: |
|
||||
self::$log->critical($msg); |
|
||||
break; |
|
||||
case ALERT: |
|
||||
self::$log->alert($msg); |
|
||||
break; |
|
||||
case EMERGENCY: |
|
||||
self::$log->emergency($msg); |
|
||||
break; |
|
||||
default: |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public static function commonLog($level, $format, $args1 = null, $arg2 = null) |
|
||||
{ |
|
||||
if(ObsLog::$log){ |
|
||||
if ($args1 === null && $arg2 === null) { |
|
||||
$msg = urldecode($format); |
|
||||
} else { |
|
||||
$msg = sprintf($format, $args1, $arg2); |
|
||||
} |
|
||||
$back = debug_backtrace(); |
|
||||
$line = $back[0]['line']; |
|
||||
$funcname = $back[1]['function']; |
|
||||
$filename = basename($back[0]['file']); |
|
||||
$message = '['.$filename.':'.$line.']: '.$msg; |
|
||||
ObsLog::writeLog($level, $message); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,415 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs; |
|
||||
|
|
||||
use Obs\Log\ObsLog; |
|
||||
use Obs\Internal\Common\SdkCurlFactory; |
|
||||
use Obs\Internal\Common\SdkStreamHandler; |
|
||||
use Obs\Internal\Common\Model; |
|
||||
use Monolog\Logger; |
|
||||
use GuzzleHttp\Client; |
|
||||
use GuzzleHttp\HandlerStack; |
|
||||
use GuzzleHttp\Handler\CurlHandler; |
|
||||
use GuzzleHttp\Handler\CurlMultiHandler; |
|
||||
use GuzzleHttp\Handler\Proxy; |
|
||||
use GuzzleHttp\Promise\Promise; |
|
||||
use Obs\Internal\Resource\Constants; |
|
||||
|
|
||||
|
|
||||
define('DEBUG', Logger::DEBUG); |
|
||||
define('INFO', Logger::INFO); |
|
||||
define('NOTICE', Logger::NOTICE); |
|
||||
define('WARNING', Logger::WARNING); |
|
||||
define('WARN', Logger::WARNING); |
|
||||
define('ERROR', Logger::ERROR); |
|
||||
define('CRITICAL', Logger::CRITICAL); |
|
||||
define('ALERT', Logger::ALERT); |
|
||||
define('EMERGENCY', Logger::EMERGENCY); |
|
||||
|
|
||||
/** |
|
||||
* @method Model createPostSignature(array $args=[]); |
|
||||
* @method Model createSignedUrl(array $args=[]); |
|
||||
* @method Model createBucket(array $args = []); |
|
||||
* @method Model listBuckets(); |
|
||||
* @method Model deleteBucket(array $args = []); |
|
||||
* @method Model listObjects(array $args = []); |
|
||||
* @method Model listVersions(array $args = []); |
|
||||
* @method Model headBucket(array $args = []); |
|
||||
* @method Model getBucketMetadata(array $args = []); |
|
||||
* @method Model getBucketLocation(array $args = []); |
|
||||
* @method Model getBucketStorageInfo(array $args = []); |
|
||||
* @method Model setBucketQuota(array $args = []); |
|
||||
* @method Model getBucketQuota(array $args = []); |
|
||||
* @method Model setBucketStoragePolicy(array $args = []); |
|
||||
* @method Model getBucketStoragePolicy(array $args = []); |
|
||||
* @method Model setBucketAcl(array $args = []); |
|
||||
* @method Model getBucketAcl(array $args = []); |
|
||||
* @method Model setBucketLogging(array $args = []); |
|
||||
* @method Model getBucketLogging(array $args = []); |
|
||||
* @method Model setBucketPolicy(array $args = []); |
|
||||
* @method Model getBucketPolicy(array $args = []); |
|
||||
* @method Model deleteBucketPolicy(array $args = []); |
|
||||
* @method Model setBucketLifecycle(array $args = []); |
|
||||
* @method Model getBucketLifecycle(array $args = []); |
|
||||
* @method Model deleteBucketLifecycle(array $args = []); |
|
||||
* @method Model setBucketWebsite(array $args = []); |
|
||||
* @method Model getBucketWebsite(array $args = []); |
|
||||
* @method Model deleteBucketWebsite(array $args = []); |
|
||||
* @method Model setBucketVersioning(array $args = []); |
|
||||
* @method Model getBucketVersioning(array $args = []); |
|
||||
* @method Model setBucketCors(array $args = []); |
|
||||
* @method Model getBucketCors(array $args = []); |
|
||||
* @method Model deleteBucketCors(array $args = []); |
|
||||
* @method Model setBucketNotification(array $args = []); |
|
||||
* @method Model getBucketNotification(array $args = []); |
|
||||
* @method Model setBucketTagging(array $args = []); |
|
||||
* @method Model getBucketTagging(array $args = []); |
|
||||
* @method Model deleteBucketTagging(array $args = []); |
|
||||
* @method Model optionsBucket(array $args = []); |
|
||||
* @method Model getFetchPolicy(array $args = []); |
|
||||
* @method Model setFetchPolicy(array $args = []); |
|
||||
* @method Model deleteFetchPolicy(array $args = []); |
|
||||
* @method Model setFetchJob(array $args = []); |
|
||||
* @method Model getFetchJob(array $args = []); |
|
||||
* |
|
||||
* @method Model putObject(array $args = []); |
|
||||
* @method Model getObject(array $args = []); |
|
||||
* @method Model copyObject(array $args = []); |
|
||||
* @method Model deleteObject(array $args = []); |
|
||||
* @method Model deleteObjects(array $args = []); |
|
||||
* @method Model getObjectMetadata(array $args = []); |
|
||||
* @method Model setObjectAcl(array $args = []); |
|
||||
* @method Model getObjectAcl(array $args = []); |
|
||||
* @method Model initiateMultipartUpload(array $args = []); |
|
||||
* @method Model uploadPart(array $args = []); |
|
||||
* @method Model copyPart(array $args = []); |
|
||||
* @method Model listParts(array $args = []); |
|
||||
* @method Model completeMultipartUpload(array $args = []); |
|
||||
* @method Model abortMultipartUpload(array $args = []); |
|
||||
* @method Model listMultipartUploads(array $args = []); |
|
||||
* @method Model optionsObject(array $args = []); |
|
||||
* @method Model restoreObject(array $args = []); |
|
||||
* |
|
||||
* @method Promise createBucketAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listBucketsAsync(callable $callback); |
|
||||
* @method Promise deleteBucketAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listObjectsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listVersionsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise headBucketAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketMetadataAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketLocationAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketStorageInfoAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketQuotaAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketQuotaAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketStoragePolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketStoragePolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketLoggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketLoggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketLifecycleAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketLifecycleAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketLifecycleAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketWebsiteAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketWebsiteAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketWebsiteAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketVersioningAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketVersioningAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketCorsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketCorsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketCorsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketNotificationAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketNotificationAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketTaggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketTaggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketTaggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise optionsBucketAsync(array $args = [], callable $callback); |
|
||||
* |
|
||||
* @method Promise putObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise copyObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteObjectsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getObjectMetadataAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setObjectAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getObjectAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise initiateMultipartUploadAsync(array $args = [], callable $callback); |
|
||||
* @method Promise uploadPartAsync(array $args = [], callable $callback); |
|
||||
* @method Promise copyPartAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listPartsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise completeMultipartUploadAsync(array $args = [], callable $callback); |
|
||||
* @method Promise abortMultipartUploadAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listMultipartUploadsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise optionsObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise restoreObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Model getFetchPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Model setFetchPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Model deleteFetchPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Model setFetchJobAsync(array $args = [], callable $callback); |
|
||||
* @method Model getFetchJobAsync(array $args = [], callable $callback); |
|
||||
* |
|
||||
*/ |
|
||||
class ObsClient |
|
||||
{ |
|
||||
|
|
||||
const SDK_VERSION = '3.21.9'; |
|
||||
|
|
||||
const AclPrivate = 'private'; |
|
||||
const AclPublicRead = 'public-read'; |
|
||||
const AclPublicReadWrite = 'public-read-write'; |
|
||||
const AclPublicReadDelivered = 'public-read-delivered'; |
|
||||
const AclPublicReadWriteDelivered = 'public-read-write-delivered'; |
|
||||
|
|
||||
const AclAuthenticatedRead = 'authenticated-read'; |
|
||||
const AclBucketOwnerRead = 'bucket-owner-read'; |
|
||||
const AclBucketOwnerFullControl = 'bucket-owner-full-control'; |
|
||||
const AclLogDeliveryWrite = 'log-delivery-write'; |
|
||||
|
|
||||
const StorageClassStandard = 'STANDARD'; |
|
||||
const StorageClassWarm = 'WARM'; |
|
||||
const StorageClassCold = 'COLD'; |
|
||||
|
|
||||
const PermissionRead = 'READ'; |
|
||||
const PermissionWrite = 'WRITE'; |
|
||||
const PermissionReadAcp = 'READ_ACP'; |
|
||||
const PermissionWriteAcp = 'WRITE_ACP'; |
|
||||
const PermissionFullControl = 'FULL_CONTROL'; |
|
||||
|
|
||||
const AllUsers = 'Everyone'; |
|
||||
|
|
||||
const GroupAllUsers = 'AllUsers'; |
|
||||
const GroupAuthenticatedUsers = 'AuthenticatedUsers'; |
|
||||
const GroupLogDelivery = 'LogDelivery'; |
|
||||
|
|
||||
const RestoreTierExpedited = 'Expedited'; |
|
||||
const RestoreTierStandard = 'Standard'; |
|
||||
const RestoreTierBulk = 'Bulk'; |
|
||||
|
|
||||
const GranteeGroup = 'Group'; |
|
||||
const GranteeUser = 'CanonicalUser'; |
|
||||
|
|
||||
const CopyMetadata = 'COPY'; |
|
||||
const ReplaceMetadata = 'REPLACE'; |
|
||||
|
|
||||
const SignatureV2 = 'v2'; |
|
||||
const SignatureV4 = 'v4'; |
|
||||
const SigantureObs = 'obs'; |
|
||||
|
|
||||
const ObjectCreatedAll = 'ObjectCreated:*'; |
|
||||
const ObjectCreatedPut = 'ObjectCreated:Put'; |
|
||||
const ObjectCreatedPost = 'ObjectCreated:Post'; |
|
||||
const ObjectCreatedCopy = 'ObjectCreated:Copy'; |
|
||||
const ObjectCreatedCompleteMultipartUpload = 'ObjectCreated:CompleteMultipartUpload'; |
|
||||
const ObjectRemovedAll = 'ObjectRemoved:*'; |
|
||||
const ObjectRemovedDelete = 'ObjectRemoved:Delete'; |
|
||||
const ObjectRemovedDeleteMarkerCreated = 'ObjectRemoved:DeleteMarkerCreated'; |
|
||||
|
|
||||
use Internal\SendRequestTrait; |
|
||||
use Internal\GetResponseTrait; |
|
||||
|
|
||||
private $factorys; |
|
||||
|
|
||||
public function __construct(array $config = []){ |
|
||||
$this ->factorys = []; |
|
||||
|
|
||||
$this -> ak = strval($config['key']); |
|
||||
$this -> sk = strval($config['secret']); |
|
||||
|
|
||||
if(isset($config['security_token'])){ |
|
||||
$this -> securityToken = strval($config['security_token']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['endpoint'])){ |
|
||||
$this -> endpoint = trim(strval($config['endpoint'])); |
|
||||
} |
|
||||
|
|
||||
if($this -> endpoint === ''){ |
|
||||
throw new \RuntimeException('endpoint is not set'); |
|
||||
} |
|
||||
|
|
||||
while($this -> endpoint[strlen($this -> endpoint)-1] === '/'){ |
|
||||
$this -> endpoint = substr($this -> endpoint, 0, strlen($this -> endpoint)-1); |
|
||||
} |
|
||||
|
|
||||
if(strpos($this-> endpoint, 'http') !== 0){ |
|
||||
$this -> endpoint = 'https://' . $this -> endpoint; |
|
||||
} |
|
||||
|
|
||||
if(isset($config['signature'])){ |
|
||||
$this -> signature = strval($config['signature']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['path_style'])){ |
|
||||
$this -> pathStyle = $config['path_style']; |
|
||||
} |
|
||||
|
|
||||
if(isset($config['region'])){ |
|
||||
$this -> region = strval($config['region']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['ssl_verify'])){ |
|
||||
$this -> sslVerify = $config['ssl_verify']; |
|
||||
}else if(isset($config['ssl.certificate_authority'])){ |
|
||||
$this -> sslVerify = $config['ssl.certificate_authority']; |
|
||||
} |
|
||||
|
|
||||
if(isset($config['max_retry_count'])){ |
|
||||
$this -> maxRetryCount = intval($config['max_retry_count']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['timeout'])){ |
|
||||
$this -> timeout = intval($config['timeout']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['socket_timeout'])){ |
|
||||
$this -> socketTimeout = intval($config['socket_timeout']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['connect_timeout'])){ |
|
||||
$this -> connectTimeout = intval($config['connect_timeout']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['chunk_size'])){ |
|
||||
$this -> chunkSize = intval($config['chunk_size']); |
|
||||
} |
|
||||
|
|
||||
if(isset($config['exception_response_mode'])){ |
|
||||
$this -> exceptionResponseMode = $config['exception_response_mode']; |
|
||||
} |
|
||||
|
|
||||
if (isset($config['is_cname'])) { |
|
||||
$this -> isCname = $config['is_cname']; |
|
||||
} |
|
||||
|
|
||||
$host = parse_url($this -> endpoint)['host']; |
|
||||
if(filter_var($host, FILTER_VALIDATE_IP) !== false) { |
|
||||
$this -> pathStyle = true; |
|
||||
} |
|
||||
|
|
||||
$handler = self::choose_handler($this); |
|
||||
|
|
||||
$this -> httpClient = new Client( |
|
||||
[ |
|
||||
'timeout' => 0, |
|
||||
'read_timeout' => $this -> socketTimeout, |
|
||||
'connect_timeout' => $this -> connectTimeout, |
|
||||
'allow_redirects' => false, |
|
||||
'verify' => $this -> sslVerify, |
|
||||
'expect' => false, |
|
||||
'handler' => HandlerStack::create($handler), |
|
||||
'curl' => [ |
|
||||
CURLOPT_BUFFERSIZE => $this -> chunkSize |
|
||||
] |
|
||||
] |
|
||||
); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public function __destruct(){ |
|
||||
$this-> close(); |
|
||||
} |
|
||||
|
|
||||
public function refresh($key, $secret, $security_token=false){ |
|
||||
$this -> ak = strval($key); |
|
||||
$this -> sk = strval($secret); |
|
||||
if($security_token){ |
|
||||
$this -> securityToken = strval($security_token); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the default User-Agent string to use with Guzzle |
|
||||
* |
|
||||
* @return string |
|
||||
*/ |
|
||||
private static function default_user_agent() |
|
||||
{ |
|
||||
static $defaultAgent = ''; |
|
||||
if (!$defaultAgent) { |
|
||||
$defaultAgent = 'obs-sdk-php/' . self::SDK_VERSION; |
|
||||
} |
|
||||
|
|
||||
return $defaultAgent; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Factory method to create a new Obs client using an array of configuration options. |
|
||||
* |
|
||||
* @param array $config Client configuration data |
|
||||
* |
|
||||
* @return ObsClient |
|
||||
*/ |
|
||||
public static function factory(array $config = []) |
|
||||
{ |
|
||||
return new ObsClient($config); |
|
||||
} |
|
||||
|
|
||||
public function close(){ |
|
||||
if($this->factorys){ |
|
||||
foreach ($this->factorys as $factory){ |
|
||||
$factory->close(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public function initLog(array $logConfig= []) |
|
||||
{ |
|
||||
ObsLog::initLog($logConfig); |
|
||||
|
|
||||
$msg = []; |
|
||||
$msg[] = '[OBS SDK Version=' . self::SDK_VERSION; |
|
||||
$msg[] = 'Endpoint=' . $this->endpoint; |
|
||||
$msg[] = 'Access Mode=' . ($this->pathStyle ? 'Path' : 'Virtual Hosting').']'; |
|
||||
|
|
||||
ObsLog::commonLog(WARNING, implode("];[", $msg)); |
|
||||
} |
|
||||
|
|
||||
private static function choose_handler($obsclient) |
|
||||
{ |
|
||||
$handler = null; |
|
||||
if (function_exists('curl_multi_exec') && function_exists('curl_exec')) { |
|
||||
$f1 = new SdkCurlFactory(50); |
|
||||
$f2 = new SdkCurlFactory(3); |
|
||||
$obsclient->factorys[] = $f1; |
|
||||
$obsclient->factorys[] = $f2; |
|
||||
$handler = Proxy::wrapSync(new CurlMultiHandler(['handle_factory' => $f1]), new CurlHandler(['handle_factory' => $f2])); |
|
||||
} elseif (function_exists('curl_exec')) { |
|
||||
$f = new SdkCurlFactory(3); |
|
||||
$obsclient->factorys[] = $f; |
|
||||
$handler = new CurlHandler(['handle_factory' => $f]); |
|
||||
} elseif (function_exists('curl_multi_exec')) { |
|
||||
$f = new SdkCurlFactory(50); |
|
||||
$obsclient->factorys[] = $f; |
|
||||
$handler = new CurlMultiHandler(['handle_factory' => $f]); |
|
||||
} |
|
||||
|
|
||||
if (ini_get('allow_url_fopen')) { |
|
||||
$handler = $handler |
|
||||
? Proxy::wrapStreaming($handler, new SdkStreamHandler()) |
|
||||
: new SdkStreamHandler(); |
|
||||
} elseif (!$handler) { |
|
||||
throw new \RuntimeException('GuzzleHttp requires cURL, the ' |
|
||||
. 'allow_url_fopen ini setting, or a custom HTTP handler.'); |
|
||||
} |
|
||||
|
|
||||
return $handler; |
|
||||
} |
|
||||
} |
|
||||
@ -1,140 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs; |
|
||||
|
|
||||
use GuzzleHttp\Psr7\Request; |
|
||||
use GuzzleHttp\Psr7\Response; |
|
||||
use Obs\Log\ObsLog; |
|
||||
|
|
||||
class ObsException extends \RuntimeException |
|
||||
{ |
|
||||
const CLIENT = 'client'; |
|
||||
|
|
||||
const SERVER = 'server'; |
|
||||
|
|
||||
private $response; |
|
||||
|
|
||||
private $request; |
|
||||
|
|
||||
private $requestId; |
|
||||
|
|
||||
private $exceptionType; |
|
||||
|
|
||||
private $exceptionCode; |
|
||||
|
|
||||
private $exceptionMessage; |
|
||||
|
|
||||
private $hostId; |
|
||||
|
|
||||
public function __construct ($message = null, $code = null, $previous = null) |
|
||||
{ |
|
||||
parent::__construct($message, $code, $previous); |
|
||||
} |
|
||||
|
|
||||
public function setExceptionCode($exceptionCode) |
|
||||
{ |
|
||||
$this->exceptionCode = $exceptionCode; |
|
||||
} |
|
||||
|
|
||||
public function getExceptionCode() |
|
||||
{ |
|
||||
return $this->exceptionCode; |
|
||||
} |
|
||||
|
|
||||
public function setExceptionMessage($exceptionMessage) |
|
||||
{ |
|
||||
$this->exceptionMessage = $exceptionMessage; |
|
||||
} |
|
||||
|
|
||||
public function getExceptionMessage() |
|
||||
{ |
|
||||
return $this->exceptionMessage ? $this->exceptionMessage : $this->message; |
|
||||
} |
|
||||
|
|
||||
public function setExceptionType($exceptionType) |
|
||||
{ |
|
||||
$this->exceptionType = $exceptionType; |
|
||||
} |
|
||||
|
|
||||
public function getExceptionType() |
|
||||
{ |
|
||||
return $this->exceptionType; |
|
||||
} |
|
||||
|
|
||||
public function setRequestId($requestId) |
|
||||
{ |
|
||||
$this->requestId = $requestId; |
|
||||
} |
|
||||
|
|
||||
public function getRequestId() |
|
||||
{ |
|
||||
return $this->requestId; |
|
||||
} |
|
||||
|
|
||||
public function setResponse(Response $response) |
|
||||
{ |
|
||||
$this->response = $response; |
|
||||
} |
|
||||
|
|
||||
public function getResponse() |
|
||||
{ |
|
||||
return $this->response; |
|
||||
} |
|
||||
|
|
||||
public function setRequest(Request $request) |
|
||||
{ |
|
||||
$this->request = $request; |
|
||||
} |
|
||||
|
|
||||
public function getRequest() |
|
||||
{ |
|
||||
return $this->request; |
|
||||
} |
|
||||
|
|
||||
public function getStatusCode() |
|
||||
{ |
|
||||
return $this->response ? $this->response->getStatusCode() : -1; |
|
||||
} |
|
||||
|
|
||||
public function setHostId($hostId){ |
|
||||
$this->hostId = $hostId; |
|
||||
} |
|
||||
|
|
||||
public function getHostId(){ |
|
||||
return $this->hostId; |
|
||||
} |
|
||||
|
|
||||
public function __toString() |
|
||||
{ |
|
||||
$message = get_class($this) . ': ' |
|
||||
. 'OBS Error Code: ' . $this->getExceptionCode() . ', ' |
|
||||
. 'Status Code: ' . $this->getStatusCode() . ', ' |
|
||||
. 'OBS Error Type: ' . $this->getExceptionType() . ', ' |
|
||||
. 'OBS Error Message: ' . ($this->getExceptionMessage() ? $this->getExceptionMessage():$this->getMessage()); |
|
||||
|
|
||||
// Add the User-Agent if available |
|
||||
if ($this->request) { |
|
||||
$message .= ', ' . 'User-Agent: ' . $this->request->getHeaderLine('User-Agent'); |
|
||||
} |
|
||||
$message .= "\n"; |
|
||||
|
|
||||
ObsLog::commonLog(INFO, "http request:status:%d, %s",$this->getStatusCode(),"code:".$this->getExceptionCode().", message:".$this->getMessage()); |
|
||||
return $message; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,642 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
/** |
|
||||
* Copyright 2019 Huawei Technologies Co.,Ltd. |
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
|
||||
* this file except in compliance with the License. You may obtain a copy of the |
|
||||
* License at |
|
||||
* |
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
* |
|
||||
* Unless required by applicable law or agreed to in writing, software distributed |
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||
* specific language governing permissions and limitations under the License. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
namespace Obs; |
|
||||
|
|
||||
use Obs\Internal\Signature\DefaultSignature; |
|
||||
use Obs\Log\ObsLog; |
|
||||
use Obs\Internal\Common\SdkCurlFactory; |
|
||||
use Obs\Internal\Common\SdkStreamHandler; |
|
||||
use Obs\Internal\Common\Model; |
|
||||
use Monolog\Logger; |
|
||||
use GuzzleHttp\Client; |
|
||||
use GuzzleHttp\HandlerStack; |
|
||||
use GuzzleHttp\Handler\CurlHandler; |
|
||||
use GuzzleHttp\Handler\CurlMultiHandler; |
|
||||
use GuzzleHttp\Handler\Proxy; |
|
||||
use GuzzleHttp\Promise\Promise; |
|
||||
use Obs\Internal\Resource\Constants; |
|
||||
|
|
||||
|
|
||||
define('DEBUG', Logger::DEBUG); |
|
||||
define('INFO', Logger::INFO); |
|
||||
define('NOTICE', Logger::NOTICE); |
|
||||
define('WARNING', Logger::WARNING); |
|
||||
define('WARN', Logger::WARNING); |
|
||||
define('ERROR', Logger::ERROR); |
|
||||
define('CRITICAL', Logger::CRITICAL); |
|
||||
define('ALERT', Logger::ALERT); |
|
||||
define('EMERGENCY', Logger::EMERGENCY); |
|
||||
|
|
||||
/** |
|
||||
* @method Model createPostSignature(array $args = []); |
|
||||
// * @method Model createSignedUrl(array $args = []); |
|
||||
* @method Model createBucket(array $args = []); |
|
||||
* @method Model listBuckets(); |
|
||||
* @method Model deleteBucket(array $args = []); |
|
||||
* @method Model listObjects(array $args = []); |
|
||||
* @method Model listVersions(array $args = []); |
|
||||
* @method Model headBucket(array $args = []); |
|
||||
* @method Model getBucketMetadata(array $args = []); |
|
||||
* @method Model getBucketLocation(array $args = []); |
|
||||
* @method Model getBucketStorageInfo(array $args = []); |
|
||||
* @method Model setBucketQuota(array $args = []); |
|
||||
* @method Model getBucketQuota(array $args = []); |
|
||||
* @method Model setBucketStoragePolicy(array $args = []); |
|
||||
* @method Model getBucketStoragePolicy(array $args = []); |
|
||||
* @method Model setBucketAcl(array $args = []); |
|
||||
* @method Model getBucketAcl(array $args = []); |
|
||||
* @method Model setBucketLogging(array $args = []); |
|
||||
* @method Model getBucketLogging(array $args = []); |
|
||||
* @method Model setBucketPolicy(array $args = []); |
|
||||
* @method Model getBucketPolicy(array $args = []); |
|
||||
* @method Model deleteBucketPolicy(array $args = []); |
|
||||
* @method Model setBucketLifecycle(array $args = []); |
|
||||
* @method Model getBucketLifecycle(array $args = []); |
|
||||
* @method Model deleteBucketLifecycle(array $args = []); |
|
||||
* @method Model setBucketWebsite(array $args = []); |
|
||||
* @method Model getBucketWebsite(array $args = []); |
|
||||
* @method Model deleteBucketWebsite(array $args = []); |
|
||||
* @method Model setBucketVersioning(array $args = []); |
|
||||
* @method Model getBucketVersioning(array $args = []); |
|
||||
* @method Model setBucketCors(array $args = []); |
|
||||
* @method Model getBucketCors(array $args = []); |
|
||||
* @method Model deleteBucketCors(array $args = []); |
|
||||
* @method Model setBucketNotification(array $args = []); |
|
||||
* @method Model getBucketNotification(array $args = []); |
|
||||
* @method Model setBucketTagging(array $args = []); |
|
||||
* @method Model getBucketTagging(array $args = []); |
|
||||
* @method Model deleteBucketTagging(array $args = []); |
|
||||
* @method Model optionsBucket(array $args = []); |
|
||||
* |
|
||||
* @method Model putObject(array $args = []); |
|
||||
* @method Model getObject(array $args = []); |
|
||||
* @method Model copyObject(array $args = []); |
|
||||
* @method Model deleteObject(array $args = []); |
|
||||
* @method Model deleteObjects(array $args = []); |
|
||||
* @method Model getObjectMetadata(array $args = []); |
|
||||
* @method Model setObjectAcl(array $args = []); |
|
||||
* @method Model getObjectAcl(array $args = []); |
|
||||
* @method Model initiateMultipartUpload(array $args = []); |
|
||||
* @method Model uploadPart(array $args = []); |
|
||||
* @method Model copyPart(array $args = []); |
|
||||
* @method Model listParts(array $args = []); |
|
||||
* @method Model completeMultipartUpload(array $args = []); |
|
||||
* @method Model abortMultipartUpload(array $args = []); |
|
||||
* @method Model listMultipartUploads(array $args = []); |
|
||||
* @method Model optionsObject(array $args = []); |
|
||||
* @method Model restoreObject(array $args = []); |
|
||||
* |
|
||||
* @method Promise createBucketAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listBucketsAsync(callable $callback); |
|
||||
* @method Promise deleteBucketAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listObjectsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listVersionsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise headBucketAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketMetadataAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketLocationAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketStorageInfoAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketQuotaAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketQuotaAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketStoragePolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketStoragePolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketLoggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketLoggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketPolicyAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketLifecycleAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketLifecycleAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketLifecycleAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketWebsiteAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketWebsiteAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketWebsiteAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketVersioningAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketVersioningAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketCorsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketCorsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketCorsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketNotificationAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketNotificationAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setBucketTaggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getBucketTaggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteBucketTaggingAsync(array $args = [], callable $callback); |
|
||||
* @method Promise optionsBucketAsync(array $args = [], callable $callback); |
|
||||
* |
|
||||
* @method Promise putObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise copyObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise deleteObjectsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getObjectMetadataAsync(array $args = [], callable $callback); |
|
||||
* @method Promise setObjectAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise getObjectAclAsync(array $args = [], callable $callback); |
|
||||
* @method Promise initiateMultipartUploadAsync(array $args = [], callable $callback); |
|
||||
* @method Promise uploadPartAsync(array $args = [], callable $callback); |
|
||||
* @method Promise copyPartAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listPartsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise completeMultipartUploadAsync(array $args = [], callable $callback); |
|
||||
* @method Promise abortMultipartUploadAsync(array $args = [], callable $callback); |
|
||||
* @method Promise listMultipartUploadsAsync(array $args = [], callable $callback); |
|
||||
* @method Promise optionsObjectAsync(array $args = [], callable $callback); |
|
||||
* @method Promise restoreObjectAsync(array $args = [], callable $callback); |
|
||||
* |
|
||||
*/ |
|
||||
class ObsImageClient |
|
||||
{ |
|
||||
|
|
||||
const SDK_VERSION = '3.20.5'; |
|
||||
|
|
||||
const AclPrivate = 'private'; |
|
||||
const AclPublicRead = 'public-read'; |
|
||||
const AclPublicReadWrite = 'public-read-write'; |
|
||||
const AclPublicReadDelivered = 'public-read-delivered'; |
|
||||
const AclPublicReadWriteDelivered = 'public-read-write-delivered'; |
|
||||
|
|
||||
const AclAuthenticatedRead = 'authenticated-read'; |
|
||||
const AclBucketOwnerRead = 'bucket-owner-read'; |
|
||||
const AclBucketOwnerFullControl = 'bucket-owner-full-control'; |
|
||||
const AclLogDeliveryWrite = 'log-delivery-write'; |
|
||||
|
|
||||
const StorageClassStandard = 'STANDARD'; |
|
||||
const StorageClassWarm = 'WARM'; |
|
||||
const StorageClassCold = 'COLD'; |
|
||||
|
|
||||
const PermissionRead = 'READ'; |
|
||||
const PermissionWrite = 'WRITE'; |
|
||||
const PermissionReadAcp = 'READ_ACP'; |
|
||||
const PermissionWriteAcp = 'WRITE_ACP'; |
|
||||
const PermissionFullControl = 'FULL_CONTROL'; |
|
||||
|
|
||||
const AllUsers = 'Everyone'; |
|
||||
|
|
||||
const GroupAllUsers = 'AllUsers'; |
|
||||
const GroupAuthenticatedUsers = 'AuthenticatedUsers'; |
|
||||
const GroupLogDelivery = 'LogDelivery'; |
|
||||
|
|
||||
const RestoreTierExpedited = 'Expedited'; |
|
||||
const RestoreTierStandard = 'Standard'; |
|
||||
const RestoreTierBulk = 'Bulk'; |
|
||||
|
|
||||
const GranteeGroup = 'Group'; |
|
||||
const GranteeUser = 'CanonicalUser'; |
|
||||
|
|
||||
const CopyMetadata = 'COPY'; |
|
||||
const ReplaceMetadata = 'REPLACE'; |
|
||||
|
|
||||
const SignatureV2 = 'v2'; |
|
||||
const SignatureV4 = 'v4'; |
|
||||
const SigantureObs = 'obs'; |
|
||||
|
|
||||
const ObjectCreatedAll = 'ObjectCreated:*'; |
|
||||
const ObjectCreatedPut = 'ObjectCreated:Put'; |
|
||||
const ObjectCreatedPost = 'ObjectCreated:Post'; |
|
||||
const ObjectCreatedCopy = 'ObjectCreated:Copy'; |
|
||||
const ObjectCreatedCompleteMultipartUpload = 'ObjectCreated:CompleteMultipartUpload'; |
|
||||
const ObjectRemovedAll = 'ObjectRemoved:*'; |
|
||||
const ObjectRemovedDelete = 'ObjectRemoved:Delete'; |
|
||||
const ObjectRemovedDeleteMarkerCreated = 'ObjectRemoved:DeleteMarkerCreated'; |
|
||||
|
|
||||
use Internal\SendRequestTrait; |
|
||||
use Internal\GetResponseTrait; |
|
||||
|
|
||||
private $factorys; |
|
||||
private $project_name;//项目名称 |
|
||||
private $project_sub_name;//项目二级路径 |
|
||||
private $custom_domain;//指定域名替换默认域名 |
|
||||
|
|
||||
public function __construct(array $config = []) |
|
||||
{ |
|
||||
$this->factorys = []; |
|
||||
|
|
||||
$this->ak = strval($config['key']); |
|
||||
$this->sk = strval($config['secret']); |
|
||||
|
|
||||
if (isset($config['project_name'])) { |
|
||||
$this->project_name = strval($config['project_name']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['project_sub_name'])) { |
|
||||
$this->project_sub_name = strval($config['project_sub_name']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['custom_domain'])) { |
|
||||
$this->custom_domain = strval($config['custom_domain']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['security_token'])) { |
|
||||
$this->securityToken = strval($config['security_token']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['endpoint'])) { |
|
||||
$this->endpoint = trim(strval($config['endpoint'])); |
|
||||
} |
|
||||
|
|
||||
if ($this->endpoint === '') { |
|
||||
throw new \RuntimeException('endpoint is not set'); |
|
||||
} |
|
||||
|
|
||||
while ($this->endpoint[strlen($this->endpoint) - 1] === '/') { |
|
||||
$this->endpoint = substr($this->endpoint, 0, strlen($this->endpoint) - 1); |
|
||||
} |
|
||||
|
|
||||
if (strpos($this->endpoint, 'http') !== 0) { |
|
||||
$this->endpoint = 'https://' . $this->endpoint; |
|
||||
} |
|
||||
|
|
||||
if (isset($config['signature'])) { |
|
||||
$this->signature = strval($config['signature']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['path_style'])) { |
|
||||
$this->pathStyle = $config['path_style']; |
|
||||
} |
|
||||
|
|
||||
if (isset($config['region'])) { |
|
||||
$this->region = strval($config['region']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['ssl_verify'])) { |
|
||||
$this->sslVerify = $config['ssl_verify']; |
|
||||
} else if (isset($config['ssl.certificate_authority'])) { |
|
||||
$this->sslVerify = $config['ssl.certificate_authority']; |
|
||||
} |
|
||||
|
|
||||
if (isset($config['max_retry_count'])) { |
|
||||
$this->maxRetryCount = intval($config['max_retry_count']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['timeout'])) { |
|
||||
$this->timeout = intval($config['timeout']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['socket_timeout'])) { |
|
||||
$this->socketTimeout = intval($config['socket_timeout']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['connect_timeout'])) { |
|
||||
$this->connectTimeout = intval($config['connect_timeout']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['chunk_size'])) { |
|
||||
$this->chunkSize = intval($config['chunk_size']); |
|
||||
} |
|
||||
|
|
||||
if (isset($config['exception_response_mode'])) { |
|
||||
$this->exceptionResponseMode = $config['exception_response_mode']; |
|
||||
} |
|
||||
|
|
||||
if (isset($config['is_cname'])) { |
|
||||
$this->isCname = $config['is_cname']; |
|
||||
} |
|
||||
|
|
||||
$host = parse_url($this->endpoint)['host']; |
|
||||
if (filter_var($host, FILTER_VALIDATE_IP) !== false) { |
|
||||
$this->pathStyle = true; |
|
||||
} |
|
||||
|
|
||||
$handler = self::choose_handler($this); |
|
||||
|
|
||||
$this->httpClient = new Client( |
|
||||
[ |
|
||||
'timeout' => 0, |
|
||||
'read_timeout' => $this->socketTimeout, |
|
||||
'connect_timeout' => $this->connectTimeout, |
|
||||
'allow_redirects' => false, |
|
||||
'verify' => $this->sslVerify, |
|
||||
'expect' => false, |
|
||||
'handler' => HandlerStack::create($handler), |
|
||||
'curl' => [ |
|
||||
CURLOPT_BUFFERSIZE => $this->chunkSize |
|
||||
] |
|
||||
] |
|
||||
); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public function __destruct() |
|
||||
{ |
|
||||
$this->close(); |
|
||||
} |
|
||||
|
|
||||
public function refresh($key, $secret, $security_token = false) |
|
||||
{ |
|
||||
$this->ak = strval($key); |
|
||||
$this->sk = strval($secret); |
|
||||
if ($security_token) { |
|
||||
$this->securityToken = strval($security_token); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the default User-Agent string to use with Guzzle |
|
||||
* |
|
||||
* @return string |
|
||||
*/ |
|
||||
private static function default_user_agent() |
|
||||
{ |
|
||||
static $defaultAgent = ''; |
|
||||
if (!$defaultAgent) { |
|
||||
$defaultAgent = 'obs-sdk-php/' . self::SDK_VERSION; |
|
||||
} |
|
||||
|
|
||||
return $defaultAgent; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Factory method to create a new Obs client using an array of configuration options. |
|
||||
* |
|
||||
* @param array $config Client configuration data |
|
||||
* |
|
||||
* @return ObsClient |
|
||||
*/ |
|
||||
public static function factory(array $config = []) |
|
||||
{ |
|
||||
return new ObsClient($config); |
|
||||
} |
|
||||
|
|
||||
public function close() |
|
||||
{ |
|
||||
if ($this->factorys) { |
|
||||
foreach ($this->factorys as $factory) { |
|
||||
$factory->close(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public function initLog(array $logConfig = []) |
|
||||
{ |
|
||||
ObsLog::initLog($logConfig); |
|
||||
|
|
||||
$msg = []; |
|
||||
$msg[] = '[OBS SDK Version=' . self::SDK_VERSION; |
|
||||
$msg[] = 'Endpoint=' . $this->endpoint; |
|
||||
$msg[] = 'Access Mode=' . ($this->pathStyle ? 'Path' : 'Virtual Hosting') . ']'; |
|
||||
|
|
||||
ObsLog::commonLog(WARNING, implode("];[", $msg)); |
|
||||
} |
|
||||
|
|
||||
private static function choose_handler($obsclient) |
|
||||
{ |
|
||||
$handler = null; |
|
||||
if (function_exists('curl_multi_exec') && function_exists('curl_exec')) { |
|
||||
$f1 = new SdkCurlFactory(50); |
|
||||
$f2 = new SdkCurlFactory(3); |
|
||||
$obsclient->factorys[] = $f1; |
|
||||
$obsclient->factorys[] = $f2; |
|
||||
$handler = Proxy::wrapSync(new CurlMultiHandler(['handle_factory' => $f1]), new CurlHandler(['handle_factory' => $f2])); |
|
||||
} elseif (function_exists('curl_exec')) { |
|
||||
$f = new SdkCurlFactory(3); |
|
||||
$obsclient->factorys[] = $f; |
|
||||
$handler = new CurlHandler(['handle_factory' => $f]); |
|
||||
} elseif (function_exists('curl_multi_exec')) { |
|
||||
$f = new SdkCurlFactory(50); |
|
||||
$obsclient->factorys[] = $f; |
|
||||
$handler = new CurlMultiHandler(['handle_factory' => $f]); |
|
||||
} |
|
||||
|
|
||||
if (ini_get('allow_url_fopen')) { |
|
||||
$handler = $handler |
|
||||
? Proxy::wrapStreaming($handler, new SdkStreamHandler()) |
|
||||
: new SdkStreamHandler(); |
|
||||
} elseif (!$handler) { |
|
||||
throw new \RuntimeException('GuzzleHttp requires cURL, the ' |
|
||||
. 'allow_url_fopen ini setting, or a custom HTTP handler.'); |
|
||||
} |
|
||||
|
|
||||
return $handler; |
|
||||
} |
|
||||
|
|
||||
public function createSignedUrl(array $args=[]) |
|
||||
{ |
|
||||
if (strcasecmp($this -> signature, 'v4') === 0) { |
|
||||
return $this -> createV4SignedUrl($args); |
|
||||
} |
|
||||
return $this->createCommonSignedUrl($this->signature,$args); |
|
||||
} |
|
||||
|
|
||||
private function createCommonSignedUrl(string $signature,array $args=[]) { |
|
||||
if(!isset($args['Method'])){ |
|
||||
$obsException = new ObsException('Method param must be specified, allowed values: GET | PUT | HEAD | POST | DELETE | OPTIONS'); |
|
||||
$obsException-> setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
$method = strval($args['Method']); |
|
||||
$bucketName = isset($args['Bucket'])? strval($args['Bucket']): null; |
|
||||
$objectKey = isset($args['Key'])? strval($args['Key']): null; |
|
||||
$specialParam = isset($args['SpecialParam'])? strval($args['SpecialParam']): null; |
|
||||
$expires = isset($args['Expires']) && is_numeric($args['Expires']) ? intval($args['Expires']): 300; |
|
||||
$objectKey = $this->genKey($objectKey); |
|
||||
|
|
||||
$headers = []; |
|
||||
if(isset($args['Headers']) && is_array($args['Headers']) ){ |
|
||||
foreach ($args['Headers'] as $key => $val){ |
|
||||
if(is_string($key) && $key !== ''){ |
|
||||
$headers[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
$queryParams = []; |
|
||||
if(isset($args['QueryParams']) && is_array($args['QueryParams']) ){ |
|
||||
foreach ($args['QueryParams'] as $key => $val){ |
|
||||
if(is_string($key) && $key !== ''){ |
|
||||
$queryParams[$key] = $val; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$constants = Constants::selectConstants($signature); |
|
||||
if($this->securityToken && !isset($queryParams[$constants::SECURITY_TOKEN_HEAD])){ |
|
||||
$queryParams[$constants::SECURITY_TOKEN_HEAD] = $this->securityToken; |
|
||||
} |
|
||||
|
|
||||
$sign = new DefaultSignature($this->ak, $this->sk, $this->pathStyle, $this->endpoint, $method, $this->signature, $this->securityToken, $this->isCname); |
|
||||
|
|
||||
$url = parse_url($this->endpoint); |
|
||||
$host = $url['host']; |
|
||||
|
|
||||
$result = ''; |
|
||||
|
|
||||
if($bucketName){ |
|
||||
if($this-> pathStyle){ |
|
||||
$result = '/' . $bucketName; |
|
||||
}else{ |
|
||||
$host = $this->isCname ? $host : $bucketName . '.' . $host; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$headers['Host'] = $this->custom_domain ?? $host; |
|
||||
|
|
||||
if($objectKey){ |
|
||||
$objectKey = $sign ->urlencodeWithSafe($objectKey); |
|
||||
$result .= '/' . $objectKey; |
|
||||
} |
|
||||
|
|
||||
$result .= '?'; |
|
||||
|
|
||||
if($specialParam){ |
|
||||
$queryParams[$specialParam] = ''; |
|
||||
} |
|
||||
|
|
||||
$queryParams[$constants::TEMPURL_AK_HEAD] = $this->ak; |
|
||||
|
|
||||
|
|
||||
if(!is_numeric($expires) || $expires < 0){ |
|
||||
$expires = 300; |
|
||||
} |
|
||||
$expires = intval($expires) + intval(microtime(true)); |
|
||||
|
|
||||
$queryParams['Expires'] = strval($expires); |
|
||||
|
|
||||
$_queryParams = []; |
|
||||
|
|
||||
foreach ($queryParams as $key => $val){ |
|
||||
$key = $sign -> urlencodeWithSafe($key); |
|
||||
$val = $sign -> urlencodeWithSafe($val); |
|
||||
$_queryParams[$key] = $val; |
|
||||
$result .= $key; |
|
||||
if($val){ |
|
||||
$result .= '=' . $val; |
|
||||
} |
|
||||
$result .= '&'; |
|
||||
} |
|
||||
|
|
||||
$canonicalstring = $sign ->makeCanonicalstring($method, $headers, $_queryParams, $bucketName, $objectKey, $expires); |
|
||||
$signatureContent = base64_encode(hash_hmac('sha1', $canonicalstring, $this->sk, true)); |
|
||||
|
|
||||
$result .= 'Signature=' . $sign->urlencodeWithSafe($signatureContent); |
|
||||
|
|
||||
$model = new Model(); |
|
||||
$model['ActualSignedRequestHeaders'] = $headers; |
|
||||
$model['SignedUrl'] = $url['scheme'] . '://' . ($this->custom_domain ?? $host) . ':' . (isset($url['port']) ? $url['port'] : (strtolower($url['scheme']) === 'https' ? '443' : '80')) . $result; |
|
||||
return $model; |
|
||||
} |
|
||||
|
|
||||
public function genKey(&$key) |
|
||||
{ |
|
||||
if (empty($this->project_name)) { |
|
||||
throw new \RuntimeException('project_name 参数有误'); |
|
||||
} |
|
||||
$extension = explode('.', $key); |
|
||||
$ext = end($extension); |
|
||||
$date_ym = date('Y-m'); |
|
||||
$date_ymd = date('Ymd'); |
|
||||
$filePath = empty($this->project_sub_name) ? $this->project_name : $this->project_name . '/' . $this->project_sub_name; |
|
||||
$filePath .= "/{$date_ym}/{$date_ymd}_"; |
|
||||
$hash_data = $this->project_name . $key . time() . mt_rand(111111, 999999); |
|
||||
$filePath .= hash('sha256', $hash_data) . '.' . $ext; |
|
||||
return $filePath; |
|
||||
} |
|
||||
|
|
||||
/************************************************ 改造内容 *******************************************************/ |
|
||||
public function __call($originMethod, $args) |
|
||||
{ |
|
||||
$method = $originMethod; |
|
||||
|
|
||||
$contents = Constants::selectRequestResource($this->signature); |
|
||||
$resource = &$contents::$RESOURCE_ARRAY; |
|
||||
$async = false; |
|
||||
if (strpos($method, 'Async') === (strlen($method) - 5)) { |
|
||||
$method = substr($method, 0, strlen($method) - 5); |
|
||||
$async = true; |
|
||||
} |
|
||||
|
|
||||
if (isset($resource['aliases'][$method])) { |
|
||||
$method = $resource['aliases'][$method]; |
|
||||
} |
|
||||
|
|
||||
$method = lcfirst($method); |
|
||||
|
|
||||
|
|
||||
$operation = isset($resource['operations'][$method]) ? |
|
||||
$resource['operations'][$method] : null; |
|
||||
|
|
||||
if (!$operation) { |
|
||||
ObsLog::commonLog(WARNING, 'unknow method ' . $originMethod); |
|
||||
$obsException = new ObsException('unknow method ' . $originMethod); |
|
||||
$obsException->setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
|
|
||||
$start = microtime(true); |
|
||||
if (!$async) { |
|
||||
ObsLog::commonLog(INFO, 'enter method ' . $originMethod . '...'); |
|
||||
$model = new Model(); |
|
||||
$model['method'] = $method; |
|
||||
$params = empty($args) ? [] : $args[0]; |
|
||||
$this->_checkParams($params);//house365::校验参数,自动生成文件路径名 |
|
||||
$this->checkMimeType($method, $params); |
|
||||
$this->doRequest($model, $operation, $params); |
|
||||
ObsLog::commonLog(INFO, 'obsclient cost ' . round(microtime(true) - $start, 3) * 1000 . ' ms to execute ' . $originMethod); |
|
||||
unset($model['method']); |
|
||||
$this->_replaceDomain($model);//house365::替换域名 |
|
||||
return $model; |
|
||||
} else { |
|
||||
if (empty($args) || !(is_callable($callback = $args[count($args) - 1]))) { |
|
||||
ObsLog::commonLog(WARNING, 'async method ' . $originMethod . ' must pass a CallbackInterface as param'); |
|
||||
$obsException = new ObsException('async method ' . $originMethod . ' must pass a CallbackInterface as param'); |
|
||||
$obsException->setExceptionType('client'); |
|
||||
throw $obsException; |
|
||||
} |
|
||||
ObsLog::commonLog(INFO, 'enter method ' . $originMethod . '...'); |
|
||||
$params = count($args) === 1 ? [] : $args[0]; |
|
||||
$this->checkMimeType($method, $params); |
|
||||
$model = new Model(); |
|
||||
$model['method'] = $method; |
|
||||
return $this->doRequestAsync($model, $operation, $params, $callback, $start, $originMethod); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
//house365::校验参数,自动生成文件路径名 |
|
||||
private function _checkParams(&$params) |
|
||||
{ |
|
||||
if (!isset($params['Key'])) { |
|
||||
throw new \RuntimeException('Key 参数有误'); |
|
||||
} |
|
||||
if (empty($this->project_name)) { |
|
||||
throw new \RuntimeException('project_name 参数有误'); |
|
||||
} |
|
||||
$extension = explode('.', $params['Key']); |
|
||||
$ext = end($extension); |
|
||||
$date_ym = date('Y-m'); |
|
||||
$date_ymd = date('Ymd'); |
|
||||
$filePath = empty($this->project_sub_name) ? $this->project_name : $this->project_name . '/' . $this->project_sub_name; |
|
||||
$filePath .= "/{$date_ym}/{$date_ymd}_"; |
|
||||
$hash_data = $this->project_name . $params['Key'] . time() . mt_rand(111111, 999999); |
|
||||
$filePath .= hash('sha256', $hash_data) . '.' . $ext; |
|
||||
$params['Key'] = $filePath; |
|
||||
} |
|
||||
|
|
||||
//house365::替换域名 |
|
||||
private function _replaceDomain(&$model) |
|
||||
{ |
|
||||
if ($this->custom_domain && $model['ObjectURL']) { |
|
||||
$origin_url = $model['ObjectURL']; |
|
||||
$url_arr = parse_url($origin_url); |
|
||||
if (!empty($url_arr['host'])) { |
|
||||
$url_ = $url_arr['scheme'] . '://' . $this->custom_domain . $url_arr['path']; |
|
||||
$url_ .= isset($url_arr['query']) ? '?' . $url_arr['query'] : ''; |
|
||||
$model['ObjectURL'] = $url_; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,48 +0,0 @@ |
|||||
Version 3.23.501 |
|
||||
基于华为3.23.5版本,增加自定义ObsImageClient |
|
||||
|
|
||||
Version 3.23.5 |
|
||||
|
|
||||
新特性: |
|
||||
1. 新增自定义域名相关接口; |
|
||||
2. 新增上传回调参数; |
|
||||
|
|
||||
资料&demo: |
|
||||
|
|
||||
修复问题: |
|
||||
1. 优化部分代码; |
|
||||
|
|
||||
---- |
|
||||
|
|
||||
Version 3.22.6 |
|
||||
|
|
||||
新特性: |
|
||||
|
|
||||
资料&demo: |
|
||||
|
|
||||
修复问题: |
|
||||
1. 修复三方依赖冲突的问题; |
|
||||
|
|
||||
---- |
|
||||
|
|
||||
Version 3.19.9 |
|
||||
|
|
||||
新特性: |
|
||||
|
|
||||
资料&demo: |
|
||||
|
|
||||
修复问题: |
|
||||
1. 修复OBS请求时,Host偶尔被异常替换的问题; |
|
||||
2. 修复特殊场景下,日志模块无法正常工作的问题; |
|
||||
3. 修复header中的正常特殊字符被url编码的问题; |
|
||||
|
|
||||
------------------------------------------------------------------------------------------------- |
|
||||
|
|
||||
Version 3.1.3 |
|
||||
新特性: |
|
||||
|
|
||||
资料&demo: |
|
||||
|
|
||||
修复问题: |
|
||||
1. 修复连接OBS服务超时时,解析request-id报错导致异常信息被截断的问题; |
|
||||
|
|
||||
@ -1,20 +0,0 @@ |
|||||
{ |
|
||||
"name" : "365taofang/huaweicloud-sdk-php-obs", |
|
||||
"description" : "OBS PHP SDK", |
|
||||
"license":"Apache-2.0", |
|
||||
"version":"3.23.501", |
|
||||
"require" : { |
|
||||
"php" : ">=5.6.0", |
|
||||
"guzzlehttp/guzzle" : "^6.3.0 || ^7.0", |
|
||||
"guzzlehttp/psr7" : "^1.4.2 || ^2.0", |
|
||||
"monolog/monolog" : "^1.23.0 || ^2.0", |
|
||||
"psr/http-message": "^1.0" |
|
||||
}, |
|
||||
|
|
||||
"keywords" :["obs", "php"], |
|
||||
"autoload": { |
|
||||
"psr-4": { |
|
||||
"Obs\\": "Obs/" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue