static PcsFileInfo *pcs_upload_form(Pcs handle, const char *path, PcsBool overwrite, PcsHttpForm form) { struct pcs *pcs = (struct pcs *)handle; char *url, *html, *dir = pcs_utils_basedir(path), *filename = pcs_utils_filename(path); cJSON *json, *item; PcsFileInfo *meta; url = pcs_http_build_url(pcs->http, URL_PCS_REST, "method", "upload", "app_id", "250528", "ondup", overwrite ? "overwrite" : "newcopy", "dir", dir, "filename", filename, "BDUSS", pcs->bduss, NULL); pcs_free(dir); pcs_free(filename); if (!url) { pcs_set_errmsg(handle, "Can't build the url."); return NULL; } html = pcs_post_httpform(pcs->http, url, form, PcsTrue); pcs_free(url); if (!html) { pcs_set_errmsg(handle, "Can't get response from the server."); return NULL; } json = cJSON_Parse(html); if (!json) { pcs_set_errmsg(handle, "Can't parse the response as json: %s", html); return NULL; } //"{\"error_code\":31062,\"error_msg\":\"file name is invalid\",\"request_id\":3071564675} item = cJSON_GetObjectItem(json, "error_code"); if (item) { int error_code = item->valueint; const char *error_msg = NULL; item = cJSON_GetObjectItem(json, "error_msg"); if (item) error_msg = item->valuestring; pcs_set_errmsg(handle, "Can't upload file. error_code: %d. error_msg: %s. raw response: %s", error_code, error_msg, html); cJSON_Delete(json); return NULL; } meta = pcs_parse_fileinfo(json); cJSON_Delete(json); if (!meta) { pcs_set_errmsg(handle, "Can't parse the response as meta"); return NULL; } return meta; }
PCS_API void pcs_slist_destroy(PcsSList *slist) { PcsSList *p = slist, *p2; while(p) { p2 = p; p = p->next; if (p2->string) pcs_free(p2->string); pcs_free(p2); } }
void my_dirent_destroy(my_dirent *link) { my_dirent *cusor, *ent; cusor = link; while(cusor) { ent = cusor; cusor = cusor->next; if (ent->path) pcs_free(ent->path); pcs_free(ent); } }
size_t pcs_http_write(char *ptr, size_t size, size_t nmemb, void *userdata) { struct pcs_http *http = (struct pcs_http *)userdata; size_t sz; char *p; if (size == 0 || nmemb == 0) { return 0; } sz = size * nmemb; if (!pcs_http_parse_http_head(http, &ptr, &sz, PcsTrue)) { if (http->strerror) pcs_free(http->strerror); http->strerror = pcs_utils_strdup("Cannot parse the http head. "); return 0; } if (sz > 0) { if (http->res_type == PCS_HTTP_RES_TYPE_NORMAL + 1) { http->res_body = pcs_http_append_bytes(http->res_body, http->res_body_size, ptr, sz); http->res_body_size += sz; } else if (http->res_type == PCS_HTTP_RES_TYPE_VALIDATE_TEXT + 1) { //验证内容正确性 p = &ptr[sz - 1]; while(p > ptr) { if (*p == 0) { if (http->strerror) pcs_free(http->strerror); http->strerror = pcs_utils_strdup("The response is not the validate text. "); return 0; } p--; } http->res_body = pcs_http_append_bytes(http->res_body, http->res_body_size, ptr, sz); http->res_body_size += sz; } else if (http->res_type == PCS_HTTP_RES_TYPE_RAW + 1) { http->res_body = pcs_http_append_bytes(http->res_body, http->res_body_size, ptr, sz); http->res_body_size += sz; } else if (http->res_type == PCS_HTTP_RES_TYPE_DOWNLOAD + 1) { if (!http->write_func) { if (http->strerror) pcs_free(http->strerror); http->strerror = pcs_utils_strdup("Have no write function. "); return 0; } return (*http->write_func)(ptr, sz, http->res_content_length, http->write_data); } else return 0; } return size * nmemb; }
PCS_API void pcs_http_destroy(PcsHttp handle) { struct pcs_http *http = (struct pcs_http *)handle; if (http->curl) curl_easy_cleanup(http->curl); if (http->res_header) pcs_free(http->res_header); if (http->res_body) pcs_free(http->res_body); if (http->res_encode) pcs_free(http->res_encode); pcs_free(http); }
static void node_destroy(HashtableNode *node, void(*free_value)(void *)) { HashtableNode *tmp, *cusor; cusor = node; while(cusor) { tmp = cusor; cusor = cusor->next; if (tmp->key) pcs_free(tmp->key); if (free_value && tmp->value) (*free_value)(tmp->value); pcs_free(tmp); } }
PCS_API PcsRes pcs_setopt(Pcs handle, PcsOption opt, void *value) { PcsRes res = PCS_OK; struct pcs *pcs = (struct pcs *)handle; switch (opt) { case PCS_OPTION_USERNAME: if (pcs->username) pcs_free(pcs->username); pcs->username = pcs_utils_strdup((char *)value); break; case PCS_OPTION_PASSWORD: if (pcs->password) pcs_free(pcs->password); pcs->password = pcs_utils_strdup((char *)value); break; case PCS_OPTION_CAPTCHA_FUNCTION: pcs->captcha_func = (PcsGetCaptchaFunction)value; break; case PCS_OPTION_CAPTCHA_FUNCTION_DATA: pcs->captcha_data = value; break; case PCS_OPTION_DOWNLOAD_WRITE_FUNCTION: pcs_http_setopt(pcs->http, PCS_HTTP_OPTION_HTTP_WRITE_FUNCTION, value); break; case PCS_OPTION_DOWNLOAD_WRITE_FUNCTION_DATA: pcs_http_setopt(pcs->http, PCS_HTTP_OPTION_HTTP_WRITE_FUNCTION_DATE, value); break; case PCS_OPTION_HTTP_RESPONSE_FUNCTION: pcs_http_setopt(pcs->http, PCS_HTTP_OPTION_HTTP_RESPONSE_FUNCTION, value); break; case PCS_OPTION_HTTP_RESPONSE_FUNCTION_DATE: pcs_http_setopt(pcs->http, PCS_HTTP_OPTION_HTTP_RESPONSE_FUNCTION_DATE, value); break; case PCS_OPTION_PROGRESS_FUNCTION: pcs_http_setopt(pcs->http, PCS_HTTP_OPTION_PROGRESS_FUNCTION, value); break; case PCS_OPTION_PROGRESS_FUNCTION_DATE: pcs_http_setopt(pcs->http, PCS_HTTP_OPTION_PROGRESS_FUNCTION_DATE, value); break; case PCS_OPTION_PROGRESS: pcs_http_setopt(pcs->http, PCS_HTTP_OPTION_PROGRESS, value); break; default: pcs_set_errmsg(handle, "Unknown option"); res = PCS_UNKNOWN_OPT; break; } return res; }
static size_t cb_get_verify_code_byurlc_curl_write(char *ptr, size_t size, size_t nmemb, void *userdata) { char **html = (char **) userdata; char *p; size_t sz, ptrsz; ptrsz = size * nmemb; if (ptrsz == 0) return ptrsz; if (*html) sz = strlen(*html); else sz = 0; size = sz + ptrsz; p = (char *) pcs_malloc(size + 1); if (!p) return 0; if (*html) { memcpy(p, *html, sz); pcs_free(*html); } memcpy(&p[sz], ptr, ptrsz); p[size] = '\0'; *html = p; return ptrsz; }
PCS_API char *pcs_utils_strcat(char *dst, const char *src, int src_len, int free_dst) { char *res = 0; int dst_len; if (!src) return dst; if (src_len == -1) src_len = strlen(src); if (src_len == 0) return dst; if (dst) dst_len = strlen(dst); else dst_len = 0; res = (char *)pcs_malloc(dst_len + src_len + 1); if (!res) return 0; memcpy(res, dst, dst_len); memcpy(res + dst_len, src, src_len); res[dst_len + src_len] = '\0'; if (dst && free_dst) pcs_free(dst); return res; }
/* * 获取路径的父路径,如果没有父路径则返回NULL。 * path - 当前路径 * len - path的字节长度,如果传入-1,则内部使用strlen()获取其长度 * 返回值需要调用pcs_free() */ char *base_dir(const char *path, int len) { char *dir, *p; if (!path) return NULL; if (len == -1) len = strlen(path); if (len == 0) return NULL; dir = (char *)pcs_malloc(len + 1); strcpy(dir, path); p = dir + len - 1; while (p > dir && *p != '/' && *p != '\\') p--; if (p == dir) { if (*p != '/' && *p != '\\') { pcs_free(dir); return NULL; } p[1] = '\0'; } else { #ifdef _WIN32 if (*(p - 1) == ':' && ((p - dir) == 2)) *(p + 1) = '\0'; else *p = '\0'; #else *p = '\0'; #endif } return dir; }
static inline int pcs_http_get_content_length_from_header(const char *header, int size) { int res = -1; char *val = NULL; const char *p = header, *key = "Content-Length", *end = NULL, *tmp; int i = 14;//strlen(key) = 14; while (*p) { if (*p == key[0] && pcs_utils_streq(p, key, i)) { tmp = p + i; PCS_SKIP_SPACE(tmp); if (*tmp != ':') continue; tmp++; PCS_SKIP_SPACE(tmp); end = tmp; while (*end && *end >= '0' && *end <= '9') end++; if (end > tmp) { val = (char *)pcs_malloc(end - tmp + 1); memcpy(val, tmp, end - tmp); val[end - tmp] = '\0'; res = atoi(val); pcs_free(val); break; } } p++; } return res; }
static void exec_cat(Pcs pcs, struct params *params) { const char *res; size_t sz; printf("\nCat %s\n", params->args[0]); res = pcs_cat(pcs, params->args[0], &sz); if (res == NULL) { printf("Cat failed: %s\n", pcs_strerror(pcs)); return; } if (params->is_rc4) { const char *rc4_key = get_rc4_key(params); char *text; RC4_CTX rc4; secure_rc4_setup(&rc4, rc4_key); text = (char *)pcs_malloc(sz + 1); memset(text, 0, sz + 1); RC4(&rc4, sz, (const unsigned char *)res, (unsigned char *)text); text[sz] = '\0'; printf(">>>\n%s\n<<<\n", text); pcs_free(text); } else { printf(">>>\n%s\n<<<\n", res); } }
PCS_API PcsHttp pcs_http_create(const char *cookie_file) { struct pcs_http *http; http = (struct pcs_http *) pcs_malloc(sizeof(struct pcs_http)); if (!http) return NULL; memset(http, 0, sizeof(struct pcs_http)); http->timeout = 0; http->connect_timeout = 10; http->curl = curl_easy_init(); if (!http->curl) { pcs_free(http); return NULL; } curl_easy_setopt(http->curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(http->curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(http->curl, CURLOPT_LOW_SPEED_LIMIT, 1024L); curl_easy_setopt(http->curl, CURLOPT_LOW_SPEED_TIME, 60L); curl_easy_setopt(http->curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(http->curl, CURLOPT_USERAGENT, USAGE); curl_easy_setopt(http->curl, CURLOPT_FOLLOWLOCATION, 1L); if (cookie_file) { curl_easy_setopt(http->curl, CURLOPT_COOKIEFILE, cookie_file); curl_easy_setopt(http->curl, CURLOPT_COOKIEJAR, cookie_file); } else { curl_easy_setopt(http->curl, CURLOPT_COOKIEFILE, ""); } return http; }
static void exec_echo_override(Pcs pcs, struct params *params) { char *text; size_t sz; PcsFileInfo *f; printf("\nOverwrite text to %s\n", params->args[0]); sz = strlen(params->args[1]); if (params->is_rc4) { const char *rc4_key = get_rc4_key2(params); RC4_CTX rc4; secure_rc4_setup(&rc4, rc4_key); text = (char *)pcs_malloc(sz + 1); memset(text, 0, sz + 1); RC4(&rc4, sz, (const unsigned char *)params->args[1], (unsigned char *)text); text[sz] = '\0'; f = pcs_upload_buffer(pcs, params->args[0], PcsTrue, text, sz); pcs_free(text); } else { text = params->args[1]; f = pcs_upload_buffer(pcs, params->args[0], PcsTrue, text, sz); } if (f) { pcs_fileinfo_destroy(f); printf("Overwirte success\n", params->args[0]); } else { printf("Overwirte failed\n", params->args[0]); } }
PCS_API char *pcs_utils_vsprintf(const char *fmt, va_list ap) { int cnt, sz=0; char *buf; va_list ap_try; #ifdef WIN32 sz = 4096; #else sz = 1024; #endif buf = (char*)pcs_malloc(sz); try_print: va_copy(ap_try, ap); cnt = vsnprintf(buf, sz - 1, fmt, ap_try); va_end(ap_try); if (cnt > sz) { pcs_free(buf); sz *= 2; buf = (char*)pcs_malloc(sz); goto try_print; } if (cnt < 0) return NULL; buf[cnt] = '\0'; return buf; }
PCS_API char *pcs_http_cookie_data(PcsHttp handle) { struct pcs_http *http = (struct pcs_http *)handle; CURLcode res; struct curl_slist *cookies; struct curl_slist *nc; char *data = NULL, *p; int sz = 0, i = 0; res = curl_easy_getinfo(http->curl, CURLINFO_COOKIELIST, &cookies); if (res != CURLE_OK) { return NULL; } nc = cookies; while (nc) { i = strlen(nc->data); if (!data) { data = (char *)pcs_malloc(i + 2); if (!data) { curl_slist_free_all(cookies); return NULL; } memcpy(data, nc->data, i); memcpy(data + i, "\n\0", 2); sz = i + 1; } else { p = (char *)pcs_malloc(sz + i + 2); if (!p) { pcs_free(data); curl_slist_free_all(cookies); return NULL; } memcpy(p, data, sz); memcpy(p + sz, nc->data, i); sz += i; memcpy(p + sz, "\n\0", 2); pcs_free(data); data = p; sz++; } nc = nc->next; } curl_slist_free_all(cookies); return data; }
void pcs_clear_errmsg(Pcs handle) { struct pcs *pcs = (struct pcs *)handle; if (pcs->errmsg) { pcs_free(pcs->errmsg); pcs->errmsg = NULL; } }
PCS_API void pcs_http_form_destroy(PcsHttp handle, PcsHttpForm post) { struct http_post *formpost = (struct http_post *)post; if (formpost) { curl_formfree(formpost->formpost); pcs_free(formpost); } }
static inline void pcs_http_reset_response(struct pcs_http *http) { if (http->res_body) pcs_free(http->res_body); if (http->res_header) pcs_free(http->res_header); if (http->res_encode) pcs_free(http->res_encode); http->res_type = PCS_HTTP_RES_TYPE_NORMAL; http->res_code = 0; http->res_header = NULL; http->res_header_size = 0; http->res_body = NULL; http->res_body_size = 0; http->res_content_length = 0; http->res_encode = 0; http->strerror = NULL; }
void shell_args_destroy_params(struct params *params) { int i; if (params->username) pcs_free(params->username); if (params->password) pcs_free(params->password); if (params->sort) pcs_free(params->sort); if (params->cookie) pcs_free(params->cookie); if (params->rc4_key) pcs_free(params->rc4_key); if (params->args) { for (i = 0; i < params->args_count; i++) { pcs_free(params->args[i]); } pcs_free(params->args); } if (params->config) pcs_free(params->config); if (params->cache) pcs_free(params->cache); pcs_free(params); }
static inline void pcs_http_prepare(struct pcs_http *http, enum HttpMethod method, const char *url, PcsBool follow_location, PcsHttpWriteFunction write_func, void *state, curl_off_t max_recv_speed, curl_off_t max_send_speed, curl_off_t resume_from, curl_off_t max_length) { pcs_http_reset_response(http); curl_easy_setopt(http->curl, CURLOPT_USERAGENT, http->usage ? http->usage : USAGE); curl_easy_setopt(http->curl, CURLOPT_URL, url); switch(method) { case HTTP_METHOD_GET: curl_easy_setopt(http->curl, CURLOPT_HTTPGET, 1L); break; case HTTP_METHOD_POST: curl_easy_setopt(http->curl, CURLOPT_POST, 1L); break; } curl_easy_setopt(http->curl, CURLOPT_HEADER, 1L); curl_easy_setopt(http->curl, CURLOPT_CONNECTTIMEOUT, (long)http->connect_timeout); curl_easy_setopt(http->curl, CURLOPT_TIMEOUT, (long)http->timeout); curl_easy_setopt(http->curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(http->curl, CURLOPT_WRITEFUNCTION, write_func); curl_easy_setopt(http->curl, CURLOPT_WRITEDATA, state); // 设置文件续传的位置给libcurl if (resume_from && max_length) { char *range = pcs_utils_sprintf("%" PRId64 "-%" PRId64, resume_from, resume_from + max_length - 1); curl_easy_setopt(http->curl, CURLOPT_RANGE, range); pcs_free(range); } else if (resume_from) { curl_easy_setopt(http->curl, CURLOPT_RESUME_FROM_LARGE, resume_from); } else { curl_easy_setopt(http->curl, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)0); } curl_easy_setopt(http->curl, CURLOPT_MAX_RECV_SPEED_LARGE, max_recv_speed ? max_recv_speed : (curl_off_t)0); curl_easy_setopt(http->curl, CURLOPT_MAX_SEND_SPEED_LARGE, max_send_speed ? max_send_speed : (curl_off_t)0); if (follow_location) curl_easy_setopt(http->curl, CURLOPT_FOLLOWLOCATION, 1L); else curl_easy_setopt(http->curl, CURLOPT_FOLLOWLOCATION, 0L); if (http->progress) { curl_easy_setopt(http->curl, CURLOPT_PROGRESSFUNCTION, http->progress_func); curl_easy_setopt(http->curl, CURLOPT_PROGRESSDATA, http->progress_data); curl_easy_setopt(http->curl, CURLOPT_NOPROGRESS, (long)0); } else { curl_easy_setopt(http->curl, CURLOPT_PROGRESSFUNCTION, NULL); curl_easy_setopt(http->curl, CURLOPT_PROGRESSDATA, NULL); curl_easy_setopt(http->curl, CURLOPT_NOPROGRESS, (long)1); } }
PCS_API void pcs_filist_destroy(PcsFileInfoList *list) { PcsFileInfoListItem *p = list->link, *p2; while(p) { p2 = p; p = p->next; pcs_filistitem_destroy(p2); } pcs_free(list); }
PCS_API char *pcs_http_build_post_data_v(PcsHttp handle, va_list args) { struct pcs_http *http = (struct pcs_http *)handle; char *name, *val, *escapval, *res = NULL, *p; int ressz; while((name = va_arg(args, char *)) != NULL) { val = va_arg(args, char *); if (name[0] == '\0') continue; escapval = curl_easy_escape(http->curl, val, 0); if (!res) { ressz = strlen(name) + strlen(escapval) + 1; res = (char *)pcs_malloc(ressz + 1); if (!res) { return NULL; } strcpy(res, name); strcat(res, "="); strcat(res, escapval); } else { ressz += strlen(name) + strlen(escapval) + 2; p = (char *)pcs_malloc(ressz + 1); if (!p) { pcs_free(res); return NULL; } strcpy(p, res); pcs_free(res); res = p; strcat(res, "&"); strcat(res, name); strcat(res, "="); strcat(res, escapval); } curl_free((void *)escapval); } return res; }
PCS_API PcsFileInfo *pcs_upload(Pcs handle, const char *path, PcsBool overwrite, const char *local_filename) { struct pcs *pcs = (struct pcs *)handle; char *filename; PcsHttpForm form = NULL; PcsFileInfo *meta; pcs_clear_errmsg(handle); filename = pcs_utils_filename(path); if (pcs_http_form_addfile(pcs->http, &form, "file", local_filename, filename) != PcsTrue) { pcs_set_errmsg(handle, "Can't build the post data."); pcs_free(filename); return NULL; } pcs_free(filename); meta = pcs_upload_form(handle, path, overwrite, form); pcs_http_form_destroy(pcs->http, form); return meta; }
void pcs_set_errmsg(Pcs handle, const char *fmt, ...) { struct pcs *pcs = (struct pcs *)handle; va_list args; if (pcs->errmsg) { pcs_free(pcs->errmsg); pcs->errmsg = NULL; } va_start(args, fmt); pcs->errmsg = pcs_utils_vsprintf(fmt, args); va_end(args); }
/*pcs_build_pan_api_url()的矢量模式*/ static char *pcs_build_pan_api_url_v(Pcs handle, const char *action, va_list args) { struct pcs *pcs = (struct pcs *)handle; char *baseurl, *url, *tt; tt = pcs_utils_sprintf("%d", (int)time(0)); baseurl = (char *)alloca(strlen(URL_PAN_API) + strlen(action) + 1); strcpy(baseurl, URL_PAN_API); strcat(baseurl, action); baseurl = pcs_http_build_url(pcs->http, baseurl, "channel", "chunlei", "clienttype", "0", "web","1", "t", tt, "bdstoken", pcs->bdstoken, NULL); pcs_free(tt); if (!baseurl) return NULL; url = pcs_http_build_url_v(pcs->http, baseurl, args); pcs_free(baseurl); return url; }
PCS_API PcsFileInfoList *pcs_list(Pcs handle, const char *dir, int pageindex, int pagesize, const char *order, PcsBool desc) { struct pcs *pcs = (struct pcs *)handle; char *page, *pagenum, *tt; PcsFileInfoList *filist = NULL; pcs_clear_errmsg(handle); page = pcs_utils_sprintf("%d", pageindex); pagenum = pcs_utils_sprintf("%d", pagesize); tt = pcs_utils_sprintf("%d", (int)time(0)); filist = pcs_pan_api_1(handle, "list", "_", tt, "dir", dir, "page", page, "num", pagenum, "order", order, desc ? "desc" : "", desc ? "1" : "0", NULL); pcs_free(page); pcs_free(pagenum); pcs_free(tt); return filist; }
PCS_API PcsRes pcs_download(Pcs handle, const char *path) { struct pcs *pcs = (struct pcs *)handle; char *url; pcs_clear_errmsg(handle); url = pcs_http_build_url(pcs->http, URL_PCS_REST, "method", "download", "app_id", "250528", "path", path, NULL); if (!url) { pcs_set_errmsg(handle, "Can't build the url."); return PCS_BUILD_URL; } if (pcs_http_get_download(pcs->http, url, PcsTrue)) { pcs_free(url); return PCS_OK; } pcs_free(url); pcs_set_errmsg(handle, "Can't download the file: %s", pcs_http_strerror(pcs->http)); return PCS_FAIL; }
PCS_API PcsRes pcs_mkdir(Pcs handle, const char *path) { struct pcs *pcs = (struct pcs *)handle; int error; char *html, *postdata, *url; pcs_clear_errmsg(handle); url = pcs_build_pan_api_url(handle, "create", "a", "commit", NULL); if (!url) { pcs_set_errmsg(handle, "Can't build the url."); return PCS_BUILD_URL; } postdata = pcs_http_build_post_data(pcs->http, "path", path, "isdir", "1", "size", "", "block_list", "[]", "method", "post", NULL); if (!postdata) { pcs_set_errmsg(handle, "Can't build the post data."); pcs_free(url); return PCS_BUILD_POST_DATA; } html = pcs_http_post(pcs->http, url, postdata, PcsTrue); pcs_free(url); pcs_free(postdata); if (!html) { pcs_set_errmsg(handle, "Can't get response from the server."); return PCS_NETWORK_ERROR; } error = pcs_get_errno_from_api_res(handle, html); if (error) { return PCS_FAIL; } return PCS_OK; }
static inline char *pcs_http_append_bytes(char *dest, int sz, char *src, int srcsz) { char *p; p = (char *) pcs_malloc(sz + srcsz + 1); if (!p) return NULL; if (dest) { memcpy(p, dest, sz); pcs_free(dest); } memcpy(&p[sz], src, srcsz); p[sz + srcsz] = '\0'; return p; }