├── .gitignore ├── BaiduPCS.sln ├── CHANGES ├── LICENSE ├── Makefile.am ├── Makefile.in ├── Makefile.old ├── README.md ├── aclocal.m4 ├── arg.c ├── arg.h ├── autom4te.cache ├── output.0 ├── output.1 ├── output.2 ├── requests ├── traces.0 ├── traces.1 └── traces.2 ├── build-aux ├── compile ├── config.guess ├── config.sub ├── depcomp ├── install-sh ├── ltmain.sh └── missing ├── cache.c ├── cache.h ├── config.h.in ├── configure ├── configure.ac ├── debian ├── baidupcs.install ├── changelog ├── compat ├── control ├── copyright ├── docs ├── libbaidupcs-dev.install ├── libbaidupcs0.install ├── rules ├── source │ ├── format │ └── local-options └── watch ├── dir.c ├── dir.h ├── docs ├── 加密后文件格式.txt ├── 如何使用.txt ├── 如何编译为静态库.txt ├── 登录逻辑.txt └── 目录结构.txt ├── hashtable.c ├── hashtable.h ├── m4 ├── .gitignore ├── ax_check_openssl.m4 ├── ax_lib_crypto.m4 ├── ax_pthread.m4 ├── libtool.m4 ├── ltoptions.m4 ├── ltsugar.m4 ├── ltversion.m4 └── lt~obsolete.m4 ├── openwrt └── Makefile ├── pcs ├── BaiduPCS.h ├── BaiduPCS_DLL.vcxproj ├── BaiduPCS_DLL.vcxproj.filters ├── cJSON.c ├── cJSON.h ├── dllmain.c ├── err_msg.c ├── openssl_aes.h ├── openssl_md5.h ├── openssl_rsa.h ├── pcs.c ├── pcs.h ├── pcs_buffer.c ├── pcs_buffer.h ├── pcs_defs.h ├── pcs_fileinfo.c ├── pcs_fileinfo.h ├── pcs_http.c ├── pcs_http.h ├── pcs_mem.c ├── pcs_mem.h ├── pcs_pan_api_resinfo.c ├── pcs_pan_api_resinfo.h ├── pcs_passport_dv.c ├── pcs_passport_dv.h ├── pcs_slist.c ├── pcs_slist.h ├── pcs_utils.c ├── pcs_utils.h ├── utf8.c └── utf8.h ├── pcs_shell.vcxproj ├── pcs_shell.vcxproj.filters ├── rb_tree ├── CHANGES ├── LICENSE ├── makefile.txt ├── misc.c ├── misc.h ├── red_black_tree.c ├── red_black_tree.h ├── stack.c ├── stack.h └── test_red_black_tree.c ├── shell.c ├── shell.h ├── utils.c ├── utils.h └── version.h /.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Release 3 | ipch 4 | *.opensdf 5 | *.sdf 6 | *.suo 7 | *.user 8 | *.exe 9 | *.o 10 | *.stackdump 11 | obj 12 | objs 13 | bin 14 | libconfig.a 15 | libpcs.a 16 | .DS_Store 17 | dependencies 18 | tags 19 | -------------------------------------------------------------------------------- /BaiduPCS.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaiduPCS_DLL", "pcs\BaiduPCS_DLL.vcxproj", "{6EDC18B3-E237-4C73-9A54-58B0BEB98998}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcs_shell", "pcs_shell.vcxproj", "{BE157AEB-7F3E-4C6F-8C8E-192D57E37A11}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Release|Win32 = Release|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {6EDC18B3-E237-4C73-9A54-58B0BEB98998}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {6EDC18B3-E237-4C73-9A54-58B0BEB98998}.Debug|Win32.Build.0 = Debug|Win32 18 | {6EDC18B3-E237-4C73-9A54-58B0BEB98998}.Release|Win32.ActiveCfg = Release|Win32 19 | {6EDC18B3-E237-4C73-9A54-58B0BEB98998}.Release|Win32.Build.0 = Release|Win32 20 | {BE157AEB-7F3E-4C6F-8C8E-192D57E37A11}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {BE157AEB-7F3E-4C6F-8C8E-192D57E37A11}.Debug|Win32.Build.0 = Debug|Win32 22 | {BE157AEB-7F3E-4C6F-8C8E-192D57E37A11}.Release|Win32.ActiveCfg = Release|Win32 23 | {BE157AEB-7F3E-4C6F-8C8E-192D57E37A11}.Release|Win32.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | 0.3.1 2017-08-24 2 | - Default 5 threads 3 | - Max 10000 threads limit 4 | 5 | 0.3 2017-08-24 6 | - New build system by @hosiet 7 | - New command "fix" 8 | - Support disk cache 9 | - Tiny fix 10 | 11 | 0.2.6 2017-03-20 12 | - Fix login 13 | 14 | 0.2.5 2016-10-20 15 | - new options '--md5' and '--thumb' for 'list' and 'search' command 16 | - bug fix 17 | 18 | 0.2.4 2015-03-07 19 | - Support max upload speed 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is under MIT license. 2 | http://www.opensource.org/licenses/mit-license.php -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | VERSION_INFO = 0:0:0 2 | 3 | AM_CFLAGS = -g -Wall 4 | #AM_CFLAGS += $(PTHREAD_CFLAGS) 5 | AM_CFLAGS += -I$(top_srcdir) 6 | AM_CFLAGS += -I$(top_srcdir)/pcs 7 | AM_CFLAGS += -I$(top_srcdir)/rb_tree 8 | ACLOCAL_AMFLAGS = -I m4 9 | 10 | COMMON_LIBS = -lm 11 | 12 | bin_PROGRAMS = baidupcs 13 | 14 | pcs_src = pcs/cJSON.c \ 15 | pcs/pcs_fileinfo.c \ 16 | pcs/pcs_http.c \ 17 | pcs/pcs_mem.c \ 18 | pcs/pcs_pan_api_resinfo.c \ 19 | pcs/pcs_slist.c \ 20 | pcs/pcs_utils.c \ 21 | pcs/err_msg.c \ 22 | pcs/utf8.c \ 23 | pcs/pcs.c \ 24 | pcs/pcs_buffer.c \ 25 | pcs/pcs_passport_dv.c 26 | 27 | shell_src = shell.c \ 28 | arg.c \ 29 | dir.c \ 30 | rb_tree/misc.c \ 31 | rb_tree/red_black_tree.c \ 32 | rb_tree/stack.c \ 33 | utils.c \ 34 | hashtable.c \ 35 | cache.c 36 | 37 | baidupcs_SOURCES = \ 38 | $(shell_src) \ 39 | $(pcs_src) 40 | 41 | baidupcs_CFLAGS = $(AM_CFLAGS) 42 | baidupcs_LDADD = $(COMMON_LIBS) 43 | 44 | lib_LTLIBRARIES = libbaidupcs.la 45 | libbaidupcs_la_SOURCES = $(pcs_src) 46 | libbaidupcs_la_LDFLAGS = -version-info $(VERSION_INFO) 47 | libbaidupcs_la_LIBADD = $(pcs_LDADD) 48 | pcsincludedir = $(includedir)/pcs 49 | pcsinclude_HEADERS = pcs/pcs.h \ 50 | pcs/pcs_buffer.h \ 51 | pcs/pcs_defs.h \ 52 | pcs/pcs_fileinfo.h \ 53 | pcs/pcs_http.h \ 54 | pcs/pcs_mem.h \ 55 | pcs/pcs_pan_api_resinfo.h \ 56 | pcs/pcs_passport_dv.h \ 57 | pcs/pcs_slist.h \ 58 | pcs/pcs_utils.h 59 | 60 | noinst_HEADERS = pcs/BaiduPCS.h \ 61 | pcs/cJSON.h \ 62 | pcs/openssl_aes.h \ 63 | pcs/openssl_md5.h \ 64 | pcs/openssl_rsa.h \ 65 | pcs/utf8.h \ 66 | shell.h \ 67 | utils.h \ 68 | version.h \ 69 | arg.h \ 70 | dir.h \ 71 | hashtable.h \ 72 | cache.h \ 73 | rb_tree/misc.h \ 74 | rb_tree/red_black_tree.h \ 75 | rb_tree/stack.h 76 | 77 | EXTRA_DIST = CHANGES README.md docs 78 | -------------------------------------------------------------------------------- /Makefile.old: -------------------------------------------------------------------------------- 1 | 2 | ver = release 3 | 4 | OS_NAME = $(shell uname -s | cut -c1-6) 5 | LC_OS_NAME = $(shell echo $(OS_NAME) | tr '[A-Z]' '[a-z]') 6 | 7 | PCS_OBJS = bin/cJSON.o \ 8 | bin/pcs.o \ 9 | bin/pcs_fileinfo.o \ 10 | bin/pcs_http.o \ 11 | bin/pcs_mem.o \ 12 | bin/pcs_pan_api_resinfo.o \ 13 | bin/pcs_slist.o \ 14 | bin/pcs_utils.o \ 15 | bin/err_msg.o \ 16 | bin/utf8.o \ 17 | bin/pcs_buffer.o \ 18 | bin/pcs_passport_dv.o 19 | 20 | SHELL_OBJS = bin/shell_arg.o \ 21 | bin/shell.o \ 22 | bin/dir.o \ 23 | bin/rb_tree_misc.o \ 24 | bin/rb_tree_stack.o \ 25 | bin/red_black_tree.o \ 26 | bin/shell_utils.o \ 27 | bin/hashtable.o \ 28 | bin/cache.o 29 | 30 | #CCFLAGS = -DHAVE_ASPRINTF -DHAVE_ICONV 31 | ifeq ($(LC_OS_NAME), cygwin) 32 | CYGWIN_CCFLAGS = -largp 33 | else 34 | CYGWIN_CCFLAGS = 35 | endif 36 | 37 | ifeq ($(LC_OS_NAME), $(filter $(LC_OS_NAME),mingw3 mingw6)) 38 | MINGW_CCFLAGS = -lshlwapi 39 | else 40 | MINGW_CCFLAGS = 41 | endif 42 | 43 | ifeq ($(LC_OS_NAME), darwin) 44 | APPLE_CCFLAGS = -I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib 45 | else 46 | APPLE_CCFLAGS = 47 | endif 48 | 49 | ifneq ($(ver), debug) 50 | $(warning "Use 'make ver=debug' to build for gdb debug.") 51 | CCFLAGS:=-D_FILE_OFFSET_BITS=64 52 | else 53 | CCFLAGS:=-g -D_FILE_OFFSET_BITS=64 -DDEBUG -D_DEBUG 54 | endif 55 | 56 | PCS_CCFLAGS = -fPIC $(CCFLAGS) $(CYGWIN_CCFLAGS) $(APPLE_CCFLAGS) $(MINGW_CCFLAGS) 57 | 58 | all: bin/pcs 59 | 60 | bin/pcs : pre $(PCS_OBJS) $(SHELL_OBJS) 61 | $(CC) -o $@ $(PCS_OBJS) $(SHELL_OBJS) $(CCFLAGS) $(CYGWIN_CCFLAGS) $(APPLE_CCFLAGS) $(MINGW_CCFLAGS) -lm -lcurl -lssl -lcrypto -lpthread 62 | 63 | bin/shell_arg.o: arg.c arg.h 64 | $(CC) -o $@ -c $(PCS_CCFLAGS) arg.c 65 | bin/shell.o: shell.c shell.h version.h dir.h 66 | $(CC) -o $@ -c $(PCS_CCFLAGS) shell.c 67 | bin/dir.o: dir.c dir.h 68 | $(CC) -o $@ -c $(PCS_CCFLAGS) dir.c 69 | bin/shell_utils.o: utils.c utils.h 70 | $(CC) -o $@ -c $(PCS_CCFLAGS) utils.c 71 | bin/hashtable.o: hashtable.c hashtable.h 72 | $(CC) -o $@ -c $(PCS_CCFLAGS) hashtable.c 73 | bin/rb_tree_misc.o: rb_tree/misc.c rb_tree/misc.h 74 | $(CC) -o $@ -c $(PCS_CCFLAGS) rb_tree/misc.c 75 | bin/rb_tree_stack.o: rb_tree/stack.c rb_tree/stack.h 76 | $(CC) -o $@ -c $(PCS_CCFLAGS) rb_tree/stack.c 77 | bin/red_black_tree.o: rb_tree/red_black_tree.c rb_tree/red_black_tree.h 78 | $(CC) -o $@ -c $(PCS_CCFLAGS) rb_tree/red_black_tree.c 79 | bin/cache.o: cache.c cache.h 80 | $(CC) -o $@ -c $(PCS_CCFLAGS) cache.c 81 | 82 | bin/cJSON.o: pcs/cJSON.c pcs/cJSON.h 83 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/cJSON.c 84 | bin/pcs.o: pcs/pcs.c pcs/pcs_defs.h pcs/pcs_mem.h pcs/pcs_utils.h pcs/pcs_slist.h pcs/pcs_http.h pcs/cJSON.h pcs/pcs.h pcs/pcs_fileinfo.h pcs/pcs_pan_api_resinfo.h 85 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs.c 86 | bin/pcs_fileinfo.o: pcs/pcs_fileinfo.c pcs/pcs_mem.h pcs/pcs_defs.h pcs/pcs_utils.h pcs/pcs_slist.h pcs/pcs_fileinfo.h 87 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_fileinfo.c 88 | bin/pcs_http.o: pcs/pcs_http.c pcs/pcs_mem.h pcs/pcs_defs.h pcs/pcs_utils.h pcs/pcs_slist.h pcs/pcs_http.h 89 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_http.c 90 | bin/pcs_mem.o: pcs/pcs_mem.c pcs/pcs_defs.h 91 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_mem.c 92 | bin/pcs_pan_api_resinfo.o: pcs/pcs_pan_api_resinfo.c pcs/pcs_mem.h pcs/pcs_defs.h pcs/pcs_pan_api_resinfo.h 93 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_pan_api_resinfo.c 94 | bin/pcs_slist.o: pcs/pcs_slist.c pcs/pcs_mem.h pcs/pcs_defs.h pcs/pcs_slist.h 95 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_slist.c 96 | bin/pcs_utils.o: pcs/pcs_utils.c pcs/pcs_mem.h pcs/pcs_defs.h pcs/pcs_utils.h pcs/pcs_slist.h 97 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_utils.c 98 | bin/err_msg.o: pcs/err_msg.c 99 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/err_msg.c 100 | bin/utf8.o: pcs/utf8.c 101 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/utf8.c 102 | bin/pcs_buffer.o: pcs/pcs_buffer.c 103 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_buffer.c 104 | bin/pcs_passport_dv.o: pcs/pcs_passport_dv.c 105 | $(CC) -o $@ -c $(PCS_CCFLAGS) pcs/pcs_passport_dv.c 106 | 107 | bin/libpcs.so: pre $(PCS_OBJS) 108 | $(CC) -shared -fPIC -o $@ $(PCS_OBJS) $(CCFLAGS) $(CYGWIN_CCFLAGS) $(APPLE_CCFLAGS) $(MINGW_CCFLAGS) -lm -lcurl -lssl -lcrypto -lpthread 109 | 110 | bin/libpcs.a : pre $(PCS_OBJS) 111 | $(AR) crv $@ $(PCS_OBJS) 112 | 113 | .PHONY : install 114 | install: 115 | cp ./bin/pcs /usr/local/bin 116 | 117 | .PHONY : uninstall 118 | uninstall: 119 | rm /usr/local/bin/pcs 120 | 121 | .PHONY : clean 122 | clean : 123 | -rm -f ./bin/*.o ./bin/*.so ./bin/pcs 124 | 125 | .PHONY : pre 126 | pre : 127 | mkdir -p bin/ 128 | -------------------------------------------------------------------------------- /arg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "pcs/pcs_mem.h" 7 | #include "arg.h" 8 | 9 | #ifndef NULL 10 | #define NULL ((void *)0) 11 | #endif 12 | 13 | /*找到str第一次出现ch的位置*/ 14 | static inline char *findchar(char *str, int ch) 15 | { 16 | char *p = str; 17 | while (*p && ((int)((unsigned int)(*p))) != ch) p++; 18 | return p; 19 | } 20 | 21 | static inline char *arg_strdup(const char *str) 22 | { 23 | char *res = 0; 24 | if (str) { 25 | res = (char *)pcs_malloc(strlen(str) + 1); 26 | if (!res) 27 | return 0; 28 | strcpy(res, str); 29 | } 30 | return res; 31 | } 32 | 33 | /*从程序路径中找到文件名开始的位置,返回开始位置的指针*/ 34 | static inline char *filename(char *path) 35 | { 36 | char *p; 37 | p = path; 38 | p += strlen(p); 39 | while (p > path && *p != '/' && *p != '\\') p--; 40 | if (*p == '/' || *p == '\\') p++; 41 | return p; 42 | } 43 | 44 | #pragma region 解析参数 45 | 46 | /*用于释放struct arg中opts哈希表中的值字段*/ 47 | static void free_opt(void *p) 48 | { 49 | if (p) pcs_free(p); 50 | } 51 | 52 | /*解析参数*/ 53 | int parse_arg(struct args *arg, int argc, char *argv[], char *(*s2utf8)(const char *s)) 54 | { 55 | int i, j = 0; 56 | char *p, *op, *val; 57 | arg->name = filename(argv[0]); 58 | for (i = 1; i < argc; ++i) { 59 | p = argv[i]; 60 | if (*p == '-') { 61 | arg->optc++; 62 | } 63 | else { 64 | arg->argc++; 65 | } 66 | } 67 | if (arg->argc > 0) arg->argc--; 68 | if (arg->optc > 0) arg->opts = ht_create((int)((float)arg->optc * HASH_EXTEND_MULTIPLIER), 0, &free_opt); 69 | if (arg->argc > 0) arg->argv = (char **)pcs_malloc(arg->argc * sizeof(char *)); 70 | for (i = 1; i < argc; ++i) { 71 | p = argv[i]; 72 | if (*p == '-') { 73 | p++; 74 | if (*p == '-') { 75 | p++; 76 | val = findchar(p, '='); 77 | if (ht_has(arg->opts, p, val - p)) return -1; /*重复指定参数*/ 78 | if (ht_add(arg->opts, p, val - p, (*val) == '=' ? (s2utf8 ? s2utf8(val + 1) : arg_strdup(val + 1)) : NULL)) 79 | return -1; /*添加到哈希表中失败*/ 80 | } 81 | else { 82 | op = p; 83 | while (*op) { 84 | if (ht_has(arg->opts, op, 1)) return -1; /*重复指定参数*/ 85 | if (ht_add(arg->opts, op, 1, NULL)) 86 | return -1; /*添加到哈希表中失败*/ 87 | op++; 88 | } 89 | } 90 | } 91 | else if (!arg->cmd) { 92 | arg->cmd = p; 93 | } 94 | else { 95 | arg->argv[j++] = s2utf8 ? s2utf8(p) : arg_strdup(p); 96 | } 97 | } 98 | return 0; 99 | } 100 | 101 | void free_args(struct args *arg) 102 | { 103 | if (arg->opts) ht_destroy(arg->opts); 104 | if (arg->argv) { 105 | int i; 106 | for (i = 0; i < arg->argc; i++) { 107 | char *p = arg->argv[i]; 108 | if (p) pcs_free(p); 109 | } 110 | pcs_free(arg->argv); 111 | } 112 | } 113 | 114 | /*判断是否存在opt选项 115 | 如果存在的话,返回1,否则返回0*/ 116 | int has_opt(struct args *arg, const char *opt) 117 | { 118 | if (arg->opts) { 119 | return ht_has(arg->opts, opt, -1); 120 | } 121 | return 0; 122 | } 123 | 124 | /*判断是否存在opt选项,如果存在的话,把其值填入 (*pValue)中,并返回1, 125 | 如果不存在的话,则设置 (*pValue) = NULL, 并返回0*/ 126 | int has_optEx(struct args *arg, const char *opt, char **pValue) 127 | { 128 | if (arg->opts) { 129 | HashtableNode *node = ht_get_node(arg->opts, opt, -1); 130 | if (node) { 131 | if (pValue) (*pValue) = node->value; 132 | return 1; 133 | } 134 | } 135 | if (pValue) (*pValue) = NULL; 136 | return 0; 137 | } 138 | 139 | /* 140 | 测试arg中可选项是否正确。 141 | arg - 142 | ... - 支持的所有可选项,以NULL结束 143 | 如果测试通过则返回0,否则返回非零值 144 | 例: 145 | if (test_arg(arg, 0, 1, "d", "e", "r", "config", NULL)) { 146 | printf("Wrong Arguments\n"); 147 | return -1; 148 | } 149 | */ 150 | int test_opts(struct args *arg, ...) 151 | { 152 | int co = 0; 153 | const char *opt; 154 | va_list ap; 155 | if (!arg->opts) return 0; 156 | va_start(ap, arg); 157 | while ((opt = va_arg(ap, const char *)) != NULL) { 158 | if (ht_has(arg->opts, opt, -1)) 159 | co++; 160 | } 161 | va_end(ap); 162 | return arg->opts->count - co; 163 | } 164 | 165 | /* 166 | 删除一个选项。 167 | 删除成功返回0,否则返回非0值。 168 | 执行成功,且 pValue不为NULL,则把被删除项的值写入 (*pValue)。注意值需要调用pcs_free() 169 | */ 170 | int remove_opt(struct args *arg, const char *opt, char **pValue) 171 | { 172 | char *val = NULL; 173 | if (!arg->opts) return -1; 174 | int rc = ht_remove(arg->opts, opt, -1, (void *)(pValue ? pValue : &val)); 175 | if (rc == 0) { 176 | if (val) pcs_free(val); 177 | arg->optc--; 178 | } 179 | return rc; 180 | } 181 | 182 | /* 183 | 判断是否存在opt选项 184 | ap - 待查询的所有可选项,以NULL结束 185 | 如果全部不存在则返回0,否则返回有几个存在 186 | 例: 187 | if (has_vopt(arg, "d", "e", "r", "config", NULL)) { 188 | printf("One of the options exists.\n"); 189 | } else { 190 | printf("All of the options not exists.\n"); 191 | } 192 | */ 193 | int has_vopts(struct args *arg, va_list ap) 194 | { 195 | int co = 0; 196 | const char *opt; 197 | if (!arg->opts) return 0; 198 | while ((opt = va_arg(ap, const char *)) != NULL) { 199 | if (ht_has(arg->opts, opt, -1)) 200 | co++; 201 | } 202 | return co; 203 | } 204 | 205 | /* 206 | 判断是否存在opt选项 207 | ap - 待查询的所有可选项,以NULL结束 208 | 如果全部不存在则返回0,否则返回有几个存在 209 | 例: 210 | if (has_vopt(arg, "d", "e", "r", "config", NULL)) { 211 | printf("One of the options exists.\n"); 212 | } else { 213 | printf("All of the options not exists.\n"); 214 | } 215 | */ 216 | int has_opts(struct args *arg, ...) 217 | { 218 | int rc = 0; 219 | va_list ap; 220 | va_start(ap, arg); 221 | rc = has_vopts(arg, ap); 222 | va_end(ap); 223 | return rc; 224 | } 225 | 226 | /* 227 | 测试arg是否正确。 228 | arg - 229 | minArgc - 允许的最少参数 230 | maxArgc - 允许的最多参数 231 | ap - 支持的所有可选项,以NULL结束 232 | 如果测试通过则返回0,否则返回非零值 233 | 例: 234 | if (test_arg(arg, 0, 1, "d", "e", "r", "config", NULL)) { 235 | printf("Wrong Arguments\n"); 236 | return -1; 237 | } 238 | */ 239 | int test_varg(struct args *arg, int minArgc, int maxArgc, va_list ap) 240 | { 241 | int co = 0; 242 | const char *opt; 243 | if (arg->argc < minArgc || arg->argc > maxArgc) return -1; 244 | if (!arg->opts) return 0; 245 | while ((opt = va_arg(ap, const char *)) != NULL) { 246 | if (ht_has(arg->opts, opt, -1)) 247 | co++; 248 | } 249 | return arg->opts->count - co; 250 | } 251 | 252 | /* 253 | 测试arg是否正确。 254 | arg - 255 | minArgc - 允许的最少参数 256 | maxArgc - 允许的最多参数 257 | ... - 支持的所有可选项,以NULL结束 258 | 如果测试通过则返回0,否则返回非零值 259 | 例: 260 | if (test_arg(arg, 0, 1, "d", "e", "r", "config", NULL)) { 261 | printf("Wrong Arguments\n"); 262 | return -1; 263 | } 264 | */ 265 | int test_arg(struct args *arg, int minArgc, int maxArgc, ...) 266 | { 267 | int rc = 0; 268 | va_list ap; 269 | va_start(ap, maxArgc); 270 | rc = test_varg(arg, minArgc, maxArgc, ap); 271 | va_end(ap); 272 | return rc; 273 | } 274 | 275 | #pragma endregion 276 | -------------------------------------------------------------------------------- /arg.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_SHELL_ARG_H_ 2 | #define _PCS_SHELL_ARG_H_ 3 | 4 | #include "hashtable.h" 5 | 6 | /*参数对象*/ 7 | struct args 8 | { 9 | char *name; 10 | char *cmd; 11 | Hashtable *opts; 12 | int optc; 13 | char **argv; 14 | int argc; 15 | }; 16 | 17 | /*解析参数*/ 18 | int parse_arg(struct args *arg, int argc, char *argv[], char *(*utf8)(const char *s)); 19 | void free_args(struct args *arg); 20 | /* 21 | 删除一个选项。 22 | 删除成功返回0,否则返回非0值。 23 | 执行成功,且 pValue不为NULL,则把被删除项的值写入 (*pValue)。注意值需要调用pcs_free() 24 | */ 25 | int remove_opt(struct args *arg, const char *opt, char **pValue); 26 | 27 | /*判断是否存在opt选项 28 | 如果存在的话,返回1,否则返回0*/ 29 | int has_opt(struct args *arg, const char *opt); 30 | 31 | /*判断是否存在opt选项,如果存在的话,把其值填入 (*pValue)中,并返回1, 32 | 如果不存在的话,则设置 (*pValue) = NULL, 并返回0*/ 33 | int has_optEx(struct args *arg, const char *opt, char **pValue); 34 | 35 | /* 36 | 测试arg中可选项是否正确。 37 | arg - 38 | ... - 支持的所有可选项,以NULL结束 39 | 如果测试通过则返回0,否则返回非零值 40 | 例: 41 | if (test_arg(arg, 0, 1, "d", "e", "r", "config", NULL)) { 42 | printf("Wrong Arguments\n"); 43 | return -1; 44 | } 45 | */ 46 | int test_opts(struct args *arg, ...); 47 | 48 | /* 49 | 判断是否存在opt选项 50 | ap - 待查询的所有可选项,以NULL结束 51 | 如果全部不存在则返回0,否则返回有几个存在 52 | 例: 53 | if (has_vopt(arg, "d", "e", "r", "config", NULL)) { 54 | printf("One of the options exists.\n"); 55 | } else { 56 | printf("All of the options not exists.\n"); 57 | } 58 | */ 59 | int has_opts(struct args *arg, ...); 60 | 61 | /* 62 | 测试arg是否正确。 63 | arg - 64 | minArgc - 允许的最少参数 65 | maxArgc - 允许的最多参数 66 | ap - 支持的所有可选项,以NULL结束 67 | 如果测试通过则返回0,否则返回非零值 68 | 例: 69 | if (test_arg(arg, 0, 1, "d", "e", "r", "config", NULL)) { 70 | printf("Wrong Arguments\n"); 71 | return -1; 72 | } 73 | */ 74 | int test_varg(struct args *arg, int minArgc, int maxArgc, va_list ap); 75 | 76 | /* 77 | 测试arg是否正确。 78 | arg - 79 | minArgc - 允许的最少参数 80 | maxArgc - 允许的最多参数 81 | ... - 支持的所有可选项,以NULL结束 82 | 如果测试通过则返回0,否则返回非零值 83 | 例: 84 | if (test_arg(arg, 0, 1, "d", "e", "r", "config", NULL)) { 85 | printf("Wrong Arguments\n"); 86 | return -1; 87 | } 88 | */ 89 | int test_arg(struct args *arg, int minArgc, int maxArgc, ...); 90 | 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /build-aux/compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2012-10-14.11; # UTC 5 | 6 | # Copyright (C) 1999-2014 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) 259 | func_cl_wrapper "$@" # Doesn't return... 260 | ;; 261 | esac 262 | 263 | ofile= 264 | cfile= 265 | 266 | for arg 267 | do 268 | if test -n "$eat"; then 269 | eat= 270 | else 271 | case $1 in 272 | -o) 273 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 274 | # So we strip '-o arg' only if arg is an object. 275 | eat=1 276 | case $2 in 277 | *.o | *.obj) 278 | ofile=$2 279 | ;; 280 | *) 281 | set x "$@" -o "$2" 282 | shift 283 | ;; 284 | esac 285 | ;; 286 | *.c) 287 | cfile=$1 288 | set x "$@" "$1" 289 | shift 290 | ;; 291 | *) 292 | set x "$@" "$1" 293 | shift 294 | ;; 295 | esac 296 | fi 297 | shift 298 | done 299 | 300 | if test -z "$ofile" || test -z "$cfile"; then 301 | # If no '-o' option was seen then we might have been invoked from a 302 | # pattern rule where we don't need one. That is ok -- this is a 303 | # normal compilation that the losing compiler can handle. If no 304 | # '.c' file was seen then we are probably linking. That is also 305 | # ok. 306 | exec "$@" 307 | fi 308 | 309 | # Name of file we expect compiler to create. 310 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 311 | 312 | # Create the lock directory. 313 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 314 | # that we are using for the .o file. Also, base the name on the expected 315 | # object file name, since that is what matters with a parallel build. 316 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 317 | while true; do 318 | if mkdir "$lockdir" >/dev/null 2>&1; then 319 | break 320 | fi 321 | sleep 1 322 | done 323 | # FIXME: race condition here if user kills between mkdir and trap. 324 | trap "rmdir '$lockdir'; exit 1" 1 2 15 325 | 326 | # Run the compile. 327 | "$@" 328 | ret=$? 329 | 330 | if test -f "$cofile"; then 331 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 332 | elif test -f "${cofile}bj"; then 333 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 334 | fi 335 | 336 | rmdir "$lockdir" 337 | exit $ret 338 | 339 | # Local Variables: 340 | # mode: shell-script 341 | # sh-indentation: 2 342 | # eval: (add-hook 'write-file-hooks 'time-stamp) 343 | # time-stamp-start: "scriptversion=" 344 | # time-stamp-format: "%:y-%02m-%02d.%02H" 345 | # time-stamp-time-zone: "UTC" 346 | # time-stamp-end: "; # UTC" 347 | # End: 348 | -------------------------------------------------------------------------------- /build-aux/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2013-10-28.13; # UTC 5 | 6 | # Copyright (C) 1996-2014 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=http://www.perl.org/ 105 | flex_URL=http://flex.sourceforge.net/ 106 | gnu_software_URL=http://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'write-file-hooks 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /cache.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #ifdef WIN32 8 | # include 9 | # include 10 | #else 11 | # include 12 | #endif 13 | 14 | #include "cache.h" 15 | #include "pcs/pcs_mem.h" 16 | 17 | #ifdef WIN32 18 | #ifndef __MINGW32__ 19 | # define lseek _lseek 20 | # define fileno _fileno 21 | # define fseeko _fseeki64 22 | # define ftello _ftelli64 23 | #endif 24 | #endif 25 | 26 | int cache_init(cathe_t *cache) 27 | { 28 | memset(cache, 0, sizeof(cathe_t)); 29 | cache->blocks.prev = &cache->blocks; 30 | cache->blocks.next = &cache->blocks; 31 | return 0; 32 | } 33 | 34 | void cache_uninit(cathe_t *cache) 35 | { 36 | if (cache) { 37 | block_t *block = cache->blocks.next, *tmp; 38 | while (block != &cache->blocks) { 39 | tmp = block; 40 | block = block->next; 41 | pcs_free(tmp->data); 42 | pcs_free(tmp); 43 | } 44 | } 45 | } 46 | 47 | int cache_reset(cathe_t *cache) 48 | { 49 | cache_uninit(cache); 50 | cache->blocks.prev = &cache->blocks; 51 | cache->blocks.next = &cache->blocks; 52 | cache->total_size = 0; 53 | return 0; 54 | } 55 | 56 | block_t *cache_newblock(curl_off_t start, char *data, size_t size) 57 | { 58 | block_t *block; 59 | block = pcs_malloc(sizeof(block_t)); 60 | if (!block) 61 | return NULL; 62 | memset(block, 0, sizeof(block_t)); 63 | block->start = start; 64 | block->size = size; 65 | block->data = pcs_malloc(size); 66 | if (!block->data) { 67 | free(block); 68 | return NULL; 69 | } 70 | memcpy(block->data, data, size); 71 | return block; 72 | } 73 | 74 | int cache_addblock(cathe_t *cache, block_t *block) 75 | { 76 | block_t *pos = cache->blocks.next; 77 | cache->total_size += block->size; 78 | /* find position */ 79 | while (pos != &cache->blocks) { 80 | if (pos->start > block->start) 81 | break; 82 | pos = pos->next; 83 | } 84 | block->next = pos; 85 | block->prev = pos->prev; 86 | pos->prev->next = block; 87 | pos->prev = block; 88 | return 0; 89 | } 90 | 91 | int cache_add(cathe_t *cache, curl_off_t start, char *data, size_t size) 92 | { 93 | block_t *block, *pos = cache->blocks.next; 94 | block = cache_newblock(start, data, size); 95 | if (!block) 96 | return -1; 97 | return cache_addblock(cache, block); 98 | } 99 | 100 | int cache_flush(cathe_t *cache) 101 | { 102 | block_t *block = cache->blocks.next; 103 | int r; 104 | while (block != &cache->blocks) { 105 | r = fseeko((cache->fp), block->start, SEEK_SET); 106 | if (r) 107 | return -1; 108 | r = fwrite(block->data, 1, block->size, cache->fp); 109 | if (r != block->size) 110 | return -1; 111 | block = block->next; 112 | } 113 | return 0; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /cache.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_SHELL_CAHCE_H 2 | #define _PCS_SHELL_CAHCE_H 3 | 4 | #include "pcs/pcs.h" 5 | 6 | #ifndef MAX_CACHE_SIZE 7 | #define MAX_CACHE_SIZE (1 * 1024) /* 1MiB */ 8 | #endif 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | typedef struct block { 15 | curl_off_t start; 16 | size_t size; 17 | char *data; 18 | struct block *prev; 19 | struct block *next; 20 | } block_t; 21 | 22 | typedef struct cache { 23 | block_t blocks; 24 | FILE *fp; 25 | size_t total_size; 26 | } cathe_t; 27 | 28 | int cache_init(cathe_t *cache); 29 | 30 | void cache_uninit(cathe_t *cache); 31 | 32 | int cache_add(cathe_t *cache, curl_off_t start, char *data, size_t size); 33 | 34 | int cache_flush(cathe_t *cache); 35 | 36 | int cache_reset(cathe_t *cache); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP 4 | systems. This function is required for `alloca.c' support on those systems. 5 | */ 6 | #undef CRAY_STACKSEG_END 7 | 8 | /* Algorithm AES in openssl crypto library */ 9 | #undef CRYPTO_WITH_AES 10 | 11 | /* Algorithm BF in openssl crypto library */ 12 | #undef CRYPTO_WITH_BF 13 | 14 | /* Algorithm CAMELLIA in openssl crypto library */ 15 | #undef CRYPTO_WITH_CAMELLIA 16 | 17 | /* Algorithm CAST in openssl crypto library */ 18 | #undef CRYPTO_WITH_CAST 19 | 20 | /* Algorithm DES in openssl crypto library */ 21 | #undef CRYPTO_WITH_DES 22 | 23 | /* Algorithm DH in openssl crypto library */ 24 | #undef CRYPTO_WITH_DH 25 | 26 | /* Algorithm DSA in openssl crypto library */ 27 | #undef CRYPTO_WITH_DSA 28 | 29 | /* Algorithm IDEA in openssl crypto library */ 30 | #undef CRYPTO_WITH_IDEA 31 | 32 | /* Algorithm MD2 in openssl crypto library */ 33 | #undef CRYPTO_WITH_MD2 34 | 35 | /* Algorithm MD4 in openssl crypto library */ 36 | #undef CRYPTO_WITH_MD4 37 | 38 | /* Algorithm MD5 in openssl crypto library */ 39 | #undef CRYPTO_WITH_MD5 40 | 41 | /* Algorithm RC2 in openssl crypto library */ 42 | #undef CRYPTO_WITH_RC2 43 | 44 | /* Algorithm RC5 in openssl crypto library */ 45 | #undef CRYPTO_WITH_RC5 46 | 47 | /* Algorithm RIPEMD in openssl crypto library */ 48 | #undef CRYPTO_WITH_RIPEMD 49 | 50 | /* Algorithm RSA in openssl crypto library */ 51 | #undef CRYPTO_WITH_RSA 52 | 53 | /* Algorithm SHA in openssl crypto library */ 54 | #undef CRYPTO_WITH_SHA 55 | 56 | /* Define to 1 if using `alloca.c'. */ 57 | #undef C_ALLOCA 58 | 59 | /* Define to 1 if you have the `alarm' function. */ 60 | #undef HAVE_ALARM 61 | 62 | /* Define to 1 if you have `alloca', as a function or macro. */ 63 | #undef HAVE_ALLOCA 64 | 65 | /* Define to 1 if you have and it should be used (not on Ultrix). 66 | */ 67 | #undef HAVE_ALLOCA_H 68 | 69 | /* Openssl crypto library is available */ 70 | #undef HAVE_CRYPTO 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_DLFCN_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_FLOAT_H 77 | 78 | /* Define to 1 if you have the `floor' function. */ 79 | #undef HAVE_FLOOR 80 | 81 | /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ 82 | #undef HAVE_FSEEKO 83 | 84 | /* Define to 1 if you have the `gettimeofday' function. */ 85 | #undef HAVE_GETTIMEOFDAY 86 | 87 | /* Define to 1 if you have the header file. */ 88 | #undef HAVE_INTTYPES_H 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #undef HAVE_LIMITS_H 92 | 93 | /* Define to 1 if you have the header file. */ 94 | #undef HAVE_LOCALE_H 95 | 96 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 97 | to 0 otherwise. */ 98 | #undef HAVE_MALLOC 99 | 100 | /* Define to 1 if you have the header file. */ 101 | #undef HAVE_MALLOC_H 102 | 103 | /* Define to 1 if you have the `memmove' function. */ 104 | #undef HAVE_MEMMOVE 105 | 106 | /* Define to 1 if you have the header file. */ 107 | #undef HAVE_MEMORY_H 108 | 109 | /* Define to 1 if you have the `memset' function. */ 110 | #undef HAVE_MEMSET 111 | 112 | /* Define to 1 if you have the `mkdir' function. */ 113 | #undef HAVE_MKDIR 114 | 115 | /* Define to 1 if you have the header file. */ 116 | #undef HAVE_OPENSSL_OPENSSLCONF_H 117 | 118 | /* Define to 1 if you have the `pow' function. */ 119 | #undef HAVE_POW 120 | 121 | /* Define if you have POSIX threads libraries and header files. */ 122 | #undef HAVE_PTHREAD 123 | 124 | /* Have PTHREAD_PRIO_INHERIT. */ 125 | #undef HAVE_PTHREAD_PRIO_INHERIT 126 | 127 | /* Define to 1 if your system has a GNU libc compatible `realloc' function, 128 | and to 0 otherwise. */ 129 | #undef HAVE_REALLOC 130 | 131 | /* Define to 1 if you have the `rmdir' function. */ 132 | #undef HAVE_RMDIR 133 | 134 | /* Define to 1 if you have the `setlocale' function. */ 135 | #undef HAVE_SETLOCALE 136 | 137 | /* Define to 1 if you have the header file. */ 138 | #undef HAVE_STDDEF_H 139 | 140 | /* Define to 1 if you have the header file. */ 141 | #undef HAVE_STDINT_H 142 | 143 | /* Define to 1 if you have the header file. */ 144 | #undef HAVE_STDLIB_H 145 | 146 | /* Define to 1 if you have the `strchr' function. */ 147 | #undef HAVE_STRCHR 148 | 149 | /* Define to 1 if you have the header file. */ 150 | #undef HAVE_STRINGS_H 151 | 152 | /* Define to 1 if you have the header file. */ 153 | #undef HAVE_STRING_H 154 | 155 | /* Define to 1 if you have the `strstr' function. */ 156 | #undef HAVE_STRSTR 157 | 158 | /* Define to 1 if you have the `strtol' function. */ 159 | #undef HAVE_STRTOL 160 | 161 | /* Define to 1 if you have the header file. */ 162 | #undef HAVE_SYS_STAT_H 163 | 164 | /* Define to 1 if you have the header file. */ 165 | #undef HAVE_SYS_TIME_H 166 | 167 | /* Define to 1 if you have the header file. */ 168 | #undef HAVE_SYS_TYPES_H 169 | 170 | /* Define to 1 if you have the header file. */ 171 | #undef HAVE_TERMIOS_H 172 | 173 | /* Define to 1 if you have the header file. */ 174 | #undef HAVE_UNISTD_H 175 | 176 | /* Define to 1 if you have the `utime' function. */ 177 | #undef HAVE_UTIME 178 | 179 | /* Define to 1 if you have the header file. */ 180 | #undef HAVE_UTIME_H 181 | 182 | /* Define to the sub-directory where libtool stores uninstalled libraries. */ 183 | #undef LT_OBJDIR 184 | 185 | /* Name of package */ 186 | #undef PACKAGE 187 | 188 | /* Define to the address where bug reports for this package should be sent. */ 189 | #undef PACKAGE_BUGREPORT 190 | 191 | /* Define to the full name of this package. */ 192 | #undef PACKAGE_NAME 193 | 194 | /* Define to the full name and version of this package. */ 195 | #undef PACKAGE_STRING 196 | 197 | /* Define to the one symbol short name of this package. */ 198 | #undef PACKAGE_TARNAME 199 | 200 | /* Define to the home page for this package. */ 201 | #undef PACKAGE_URL 202 | 203 | /* Define to the version of this package. */ 204 | #undef PACKAGE_VERSION 205 | 206 | /* Define to necessary symbol if this constant uses a non-standard name on 207 | your system. */ 208 | #undef PTHREAD_CREATE_JOINABLE 209 | 210 | /* If using the C implementation of alloca, define if you know the 211 | direction of stack growth for your system; otherwise it will be 212 | automatically deduced at runtime. 213 | STACK_DIRECTION > 0 => grows toward higher addresses 214 | STACK_DIRECTION < 0 => grows toward lower addresses 215 | STACK_DIRECTION = 0 => direction of growth unknown */ 216 | #undef STACK_DIRECTION 217 | 218 | /* Define to 1 if you have the ANSI C header files. */ 219 | #undef STDC_HEADERS 220 | 221 | /* Define to 1 if you can safely include both and . */ 222 | #undef TIME_WITH_SYS_TIME 223 | 224 | /* Enable extensions on AIX 3, Interix. */ 225 | #ifndef _ALL_SOURCE 226 | # undef _ALL_SOURCE 227 | #endif 228 | /* Enable GNU extensions on systems that have them. */ 229 | #ifndef _GNU_SOURCE 230 | # undef _GNU_SOURCE 231 | #endif 232 | /* Enable threading extensions on Solaris. */ 233 | #ifndef _POSIX_PTHREAD_SEMANTICS 234 | # undef _POSIX_PTHREAD_SEMANTICS 235 | #endif 236 | /* Enable extensions on HP NonStop. */ 237 | #ifndef _TANDEM_SOURCE 238 | # undef _TANDEM_SOURCE 239 | #endif 240 | /* Enable general extensions on Solaris. */ 241 | #ifndef __EXTENSIONS__ 242 | # undef __EXTENSIONS__ 243 | #endif 244 | 245 | 246 | /* Version number of package */ 247 | #undef VERSION 248 | 249 | /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ 250 | #undef _LARGEFILE_SOURCE 251 | 252 | /* Define to 1 if on MINIX. */ 253 | #undef _MINIX 254 | 255 | /* Define to 2 if the system does not provide POSIX.1 features except with 256 | this defined. */ 257 | #undef _POSIX_1_SOURCE 258 | 259 | /* Define to 1 if you need to in order for `stat' and other things to work. */ 260 | #undef _POSIX_SOURCE 261 | 262 | /* Define for Solaris 2.5.1 so the uint32_t typedef from , 263 | , or is not used. If the typedef were allowed, the 264 | #define below would cause a syntax error. */ 265 | #undef _UINT32_T 266 | 267 | /* Define for Solaris 2.5.1 so the uint64_t typedef from , 268 | , or is not used. If the typedef were allowed, the 269 | #define below would cause a syntax error. */ 270 | #undef _UINT64_T 271 | 272 | /* Define to `__inline__' or `__inline' if that's what the C compiler 273 | calls it, or to nothing if 'inline' is not supported under any name. */ 274 | #ifndef __cplusplus 275 | #undef inline 276 | #endif 277 | 278 | /* Define to the type of a signed integer type of width exactly 64 bits if 279 | such a type exists and the standard includes do not define it. */ 280 | #undef int64_t 281 | 282 | /* Define to rpl_malloc if the replacement function should be used. */ 283 | #undef malloc 284 | 285 | /* Define to rpl_realloc if the replacement function should be used. */ 286 | #undef realloc 287 | 288 | /* Define to `unsigned int' if does not define. */ 289 | #undef size_t 290 | 291 | /* Define to the type of an unsigned integer type of width exactly 32 bits if 292 | such a type exists and the standard includes do not define it. */ 293 | #undef uint32_t 294 | 295 | /* Define to the type of an unsigned integer type of width exactly 64 bits if 296 | such a type exists and the standard includes do not define it. */ 297 | #undef uint64_t 298 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([baidupcs], [0.2.6], [https://github.com/GangZhuo/BaiduPCS]) 6 | AC_CONFIG_AUX_DIR([build-aux]) 7 | AC_CONFIG_SRCDIR([arg.c]) 8 | AC_CONFIG_HEADERS([config.h]) 9 | AC_CONFIG_MACRO_DIR([m4]) 10 | AC_USE_SYSTEM_EXTENSIONS 11 | 12 | dnl Check for lib 13 | AC_ENABLE_STATIC 14 | AC_ENABLE_SHARED 15 | LT_INIT 16 | 17 | AM_INIT_AUTOMAKE([subdir-objects foreign]) 18 | 19 | # Checks for programs. 20 | AC_PROG_CC 21 | 22 | # Checks for libraries. 23 | dnl pthread first 24 | ACX_PTHREAD 25 | AX_CHECK_OPENSSL 26 | AX_LIB_CRYPTO([auto]) 27 | LIBS="$OPENSSL_LIBS $PTHREAD_LIBS $LIBS" 28 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 29 | CC="$PTHREAD_CC" 30 | 31 | dnl Add library linking for mingw 32 | case $host in 33 | *-mingw*) 34 | LIBS="$LIBS -lshlwapi" 35 | ;; 36 | *-cygwin*) 37 | LIBS="$LIBS -largp" 38 | esac 39 | 40 | dnl Check libcurl 41 | AC_CHECK_LIB( 42 | [curl], 43 | [curl_version], 44 | [LIBS="-lcurl $LIBS"], 45 | [AC_MSG_FAILURE([Could not find libcurl.])] 46 | ) 47 | 48 | # Checks for header files. 49 | AC_FUNC_ALLOCA 50 | AC_CHECK_HEADERS([float.h inttypes.h limits.h locale.h malloc.h stddef.h stdint.h stdlib.h string.h termios.h unistd.h utime.h]) 51 | 52 | # Checks for typedefs, structures, and compiler characteristics. 53 | AC_C_INLINE 54 | AC_TYPE_INT64_T 55 | AC_TYPE_SIZE_T 56 | AC_TYPE_UINT32_T 57 | AC_TYPE_UINT64_T 58 | 59 | # Checks for library functions. 60 | AC_FUNC_FSEEKO 61 | AC_FUNC_MALLOC 62 | AC_FUNC_MKTIME 63 | AC_FUNC_REALLOC 64 | AC_FUNC_STRNLEN 65 | AC_CHECK_FUNCS([floor gettimeofday memmove memset mkdir pow rmdir setlocale strchr strstr strtol utime]) 66 | 67 | AC_CONFIG_FILES([Makefile]) 68 | AC_OUTPUT 69 | -------------------------------------------------------------------------------- /debian/baidupcs.install: -------------------------------------------------------------------------------- 1 | baidupcs usr/bin/ 2 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | baidupcs (0.2.6-1) unstable; urgency=low 2 | 3 | * Initial release. 4 | 5 | -- Boyuan Yang <073plan@gmail.com> Tue, 23 May 2017 15:51:46 +0800 6 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: baidupcs 2 | Section: net 3 | Priority: optional 4 | Maintainer: Boyuan Yang <073plan@gmail.com> 5 | Build-Depends: 6 | debhelper (>= 9), 7 | dh-autoreconf, 8 | libssl-dev, 9 | libcurl4-openssl-dev, 10 | Standards-Version: 3.9.8 11 | Homepage: https://github.com/GangZhuo/BaiduPCS 12 | 13 | Package: baidupcs 14 | Architecture: any 15 | Depends: 16 | ${misc:Depends}, 17 | ${shlibs:Depends}, 18 | Description: Command-line Baidu cloud disk utility 19 | A command line tool to manipulate Baidu Cloud Disk files (pan.baidu.com). 20 | 21 | Package: libbaidupcs-dev 22 | Architecture: any 23 | Multi-Arch: same 24 | Section: libdevel 25 | Depends: 26 | libbaidupcs0 (= ${binary:Version}), 27 | ${misc:Depends}, 28 | Description: Baidu cloud disk manipulation library (development files) 29 | Libbaidupcs is a library to manipulate files in Baidu cloud disk. 30 | . 31 | This package provides C header files for the library. 32 | 33 | Package: libbaidupcs0 34 | Architecture: any 35 | Multi-Arch: same 36 | Section: libs 37 | Pre-Depends: 38 | ${misc:Pre-Depends}, 39 | Depends: 40 | ${misc:Depends}, 41 | ${shlibs:Depends}, 42 | Description: Baidu cloud disk manipulation library (shared library) 43 | Libbaidupcs is a library to manipulate files in Baidu cloud disk. 44 | . 45 | This package provides shared libraries. 46 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: baidupcs 3 | Source: https://github.com/GangZhuo/BaiduPCS 4 | 5 | Files: * 6 | Copyright: 2014-2017, Gang Zhuo 7 | License: Expat 8 | 9 | Files: debian/* 10 | Copyright: 2017 Boyuan Yang <073plan@gmail.com> 11 | License: Expat 12 | 13 | Files: pcs/cJSON.c 14 | Copyright: 2009 Dave Gamble 15 | License: Expat 16 | 17 | Files: pcs/cJSON.h 18 | Copyright: 2009 Dave Gamble 19 | License: Expat 20 | 21 | Files: pcs/openssl_*.h 22 | Copyright: 1998-2002 The OpenSSL Project. 23 | License: OpenSSL 24 | Redistribution and use in source and binary forms, with or without 25 | modification, are permitted provided that the following conditions 26 | are met: 27 | . 28 | 1. Redistributions of source code must retain the above copyright 29 | notice, this list of conditions and the following disclaimer. 30 | . 31 | 2. Redistributions in binary form must reproduce the above copyright 32 | notice, this list of conditions and the following disclaimer in 33 | the documentation and/or other materials provided with the 34 | distribution. 35 | . 36 | 3. All advertising materials mentioning features or use of this 37 | software must display the following acknowledgment: 38 | "This product includes software developed by the OpenSSL Project 39 | for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 40 | . 41 | 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 42 | endorse or promote products derived from this software without 43 | prior written permission. For written permission, please contact 44 | openssl-core@openssl.org. 45 | . 46 | 5. Products derived from this software may not be called "OpenSSL" 47 | nor may "OpenSSL" appear in their names without prior written 48 | permission of the OpenSSL Project. 49 | . 50 | 6. Redistributions of any form whatsoever must retain the following 51 | acknowledgment: 52 | "This product includes software developed by the OpenSSL Project 53 | for use in the OpenSSL Toolkit (http://www.openssl.org/)" 54 | . 55 | THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 56 | EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 58 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 59 | ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 60 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 61 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 62 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 64 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 65 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 66 | OF THE POSSIBILITY OF SUCH DAMAGE. 67 | 68 | License: Expat 69 | Permission is hereby granted, free of charge, to any person obtaining a copy 70 | of this software and associated documentation files (the "Software"), to deal 71 | in the Software without restriction, including without limitation the rights 72 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 73 | copies of the Software, and to permit persons to whom the Software is 74 | furnished to do so, subject to the following conditions: 75 | . 76 | The above copyright notice and this permission notice shall be included in 77 | all copies or substantial portions of the Software. 78 | . 79 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 80 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 81 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 82 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 83 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 84 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 85 | THE SOFTWARE. 86 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README.md 2 | docs 3 | -------------------------------------------------------------------------------- /debian/libbaidupcs-dev.install: -------------------------------------------------------------------------------- 1 | usr/include 2 | usr/lib/*/libbaidupcs.so 3 | -------------------------------------------------------------------------------- /debian/libbaidupcs0.install: -------------------------------------------------------------------------------- 1 | usr/lib/*/libbaidupcs.so.* 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # You must remove unused comment lines for the released package. 3 | #export DH_VERBOSE = 1 4 | export DEB_BUILD_MAINT_OPTIONS = hardening=+all 5 | export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic 6 | export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed 7 | 8 | %: 9 | dh $@ --with autoreconf 10 | 11 | #override_dh_auto_install: 12 | # dh_auto_install -- prefix=/usr 13 | 14 | #override_dh_install: 15 | # dh_install --list-missing -X.pyc -X.pyo 16 | 17 | override_dh_installchangelogs: 18 | dh_installchangelogs -k CHANGES 19 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/source/local-options: -------------------------------------------------------------------------------- 1 | #abort-on-upstream-changes 2 | #unapply-patches 3 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=4 2 | opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%baidupcs-$1.tar.gz%" \ 3 | https://github.com/GangZhuo/baidupcs/tags \ 4 | (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate 5 | -------------------------------------------------------------------------------- /dir.h: -------------------------------------------------------------------------------- 1 | 2 | /*操作系统相关,用于操作文件或目录*/ 3 | 4 | #ifndef _PCS_SHELL_DIR_H_ 5 | #define _PCS_SHELL_DIR_H_ 6 | 7 | #define DEFAULT_MKDIR_ACCESS 0750 /*创建目录时默认权限,只有非Windows系统使用*/ 8 | 9 | #define MKDIR_OK 0 /*目录创建成功*/ 10 | #define MKDIR_FAIL 1 /*目录创建失败*/ 11 | #define MKDIR_TARGET_IS_FILE 2 /*本地存在,且是文件*/ 12 | 13 | 14 | typedef struct LocalFileInfo LocalFileInfo; 15 | 16 | struct LocalFileInfo 17 | { 18 | char *path; 19 | const char *filename; 20 | int isdir; 21 | time_t mtime; 22 | int64_t size; 23 | LocalFileInfo *parent; 24 | LocalFileInfo *next; 25 | int filecount; /*当是目录时,存储目录下文件的数量。递归统计。*/ 26 | 27 | void *userdata; 28 | }; 29 | 30 | /*释放掉LocalFileInfo对象*/ 31 | void DestroyLocalFileInfo(LocalFileInfo *info); 32 | 33 | /*释放掉LocalFileInfo链表*/ 34 | void DestroyLocalFileInfoLink(LocalFileInfo *link); 35 | 36 | /* 37 | * 获取指定文件或目录的信息 38 | * file - 文件或目录的路径 39 | * 如果文件或目录不存在,则返回NULL;否则返回其LocalFileInfo对象。 40 | */ 41 | LocalFileInfo *GetLocalFileInfo(const char *file); 42 | 43 | /* 44 | * 获取dir目录下的所有文件或目录。 45 | * pLink - 用于接收链表的指针。 46 | * dir - 目标目录路径 47 | * recursion - 是否递归列出 48 | * on - 当获取到一个对象后的回调函数 49 | * 回调函数参数: 50 | * info - 当前获取到的文件 51 | * parent - 当前获取到的文件的父目录 52 | * state - 状态值,有用户传入 53 | * state - 要传递到回调函数第三个参数的值 54 | * 成功后返回文件和目录的数量,失败返回负数 55 | */ 56 | int GetDirectoryFiles(LocalFileInfo **pLink, const char *dir, int recursive, 57 | void(*on)(LocalFileInfo *info, LocalFileInfo *parent, void *state), void *state); 58 | 59 | /*设置文件的最后修改时间。 60 | 如果执行成功则返回0, 61 | 否则返回非0值。*/ 62 | int SetFileLastModifyTime(const char *file, time_t mtime); 63 | 64 | /* 65 | * 递归创建目录 66 | * path - 待创建的目录 67 | * 如果成功则返回MKDIR_OK,否则返回错误码,可能错误码有: MKDIR_FAIL, MKDIR_TARGET_IS_FILE。 68 | */ 69 | int CreateDirectoryRecursive(const char *path); 70 | 71 | /*递归删除文件或目录 72 | 成功返回0,否则返回非0值 73 | */ 74 | int DeleteFileRecursive(const char *path); 75 | 76 | 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /docs/加密后文件格式.txt: -------------------------------------------------------------------------------- 1 | 2 | pcs API v1.0.6 开始支持 AES-CBC-128, AES-CBC-192 和 AES-CBC-256 加密。 3 | 4 | 加密后文件,分为三部分。开始的16字节为文件头,紧跟着的是密文,最后16字节是明文的MD5值。 5 | 6 | 16字节文件头定义如下: 7 | struct PcsAesHead 8 | { 9 | int magic; /* 使用大端存储0x41455300,即字节顺序是0x41 0x45 0x53 0x00。用于标识加密方法 */ 10 | int bits; /* 使用大端存储,其值可以是128, 192和256,用于区分是AES-CBC-128,AES-CBC-192, AES-CBC-256加密方法 */ 11 | int polish; /* AES-CBC 加密要求正文必须是16字节倍数,如果不足,程序会自动补0,此值记录补了多少字节的0。大端存储 */ 12 | int reserve; /* 保留 */ 13 | }; 14 | 15 | 密文长度必须是16字节的倍数。 16 | 17 | 最后16位是明文的MD5值,用于校验解密后的明文是否正确。 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/如何使用.txt: -------------------------------------------------------------------------------- 1 | 2 | 使用步骤大体上如下: 3 | 1. 使用 pcs_create() 创建一个Pcs对象。该函数需要传入cookie文件的路径, 4 | Pcs将使用该文件中存储的Cookie。 5 | 当Pcs对象释放后,将把新的Cookie写入到该文件中。 6 | 2. 使用 pcs_islogin() 函数获取是否已经登录。 7 | 3. 如果已经登录,则可以使用 pcs_sysUID() 函数获取登录用户的UID。 8 | 4. 如果未登录,则需要先设定识别验证码的回调函数,然后使用pcs_login()函数登录。 9 | 可以使用 pcs_setopt 和 pcs_setopts 来设定获取验证码的回调函数。 10 | 5. 登录成功后,即可使用 pcs_quota, pcs_list, pcs_upload等函数,具体参考 pcs.h 中的定义。 11 | 6. 使用完成后,使用 pcs_destroy 释放pcs对象。 12 | 13 | 示例1: 14 | PcsBool cb_get_verify_code(unsigned char *ptr, size_t size, char *captcha, size_t captchaSize, void *state) 15 | { 16 | FILE *pf; 17 | 18 | pf = fopen("~/captcha.git", "wb"); 19 | if (!pf) 20 | return PcsFalse; 21 | fwrite(ptr, 1, size, pf); 22 | fclose(pf); 23 | printf("The captcha image saved at %s\nPlease input the verify code: ", "~/captcha.git"); 24 | get_string_from_std_input(captcha, captchaSize); 25 | return PcsTrue; 26 | } 27 | 28 | void show_quota(Pcs pcs) 29 | { 30 | PcsRes pcsres; 31 | UInt64 quota, used; 32 | char str[32] = {0}; 33 | pcsres = pcs_quota(pcs, "a, &used); 34 | if (pcsres != PCS_OK) { 35 | printf("Get quota failed: %s\n", pcs_strerror(pcs, pcsres)); 36 | return; 37 | } 38 | printf("Quota: "); 39 | pcs_utils_readable_size((double)used, str, 30, NULL); 40 | printf("%s", str); 41 | putchar('/'); 42 | pcs_utils_readable_size((double)quota, str, 30, NULL); 43 | printf("%s", str); 44 | printf("\n"); 45 | } 46 | 47 | int main() 48 | { 49 | Pcs pcs; 50 | PcsRes pcsres; 51 | 52 | /* 创建一个Pcs对象 */ 53 | pcs = pcs_create(cookie_file); 54 | if ((pcsres = pcs_islogin(pcs)) != PCS_LOGIN) { 55 | pcs_setopts(pcs, 56 | PCS_OPTION_USERNAME, username, 57 | PCS_OPTION_PASSWORD, password, 58 | PCS_OPTION_END); 59 | pcs_setopt(pcs, PCS_OPTION_CAPTCHA_FUNCTION, cb_get_verify_code); 60 | /* 61 | 你也可以把 pcs_setopt(pcs, PCS_OPTION_CAPTCHA_FUNCTION, cb_get_verify_code); 合并到pcs_setopts中去,如: 62 | pcs_setopts(pcs, 63 | PCS_OPTION_USERNAME, username, 64 | PCS_OPTION_PASSWORD, password, 65 | PCS_OPTION_CAPTCHA_FUNCTION, cb_get_verify_code, 66 | PCS_OPTION_END); 67 | */ 68 | 69 | if ((pcsres = pcs_login(pcs)) != PCS_OK) { 70 | printf("Login Failed: %s\n", pcs_strerror(pcs, pcsres)); 71 | } 72 | else { 73 | printf("Login Success, UID: %s\n", pcs_sysUID(pcs)); 74 | show_quota(pcs); 75 | } 76 | } 77 | else { 78 | printf("UID: %s\n", pcs_sysUID(pcs)); 79 | show_quota(pcs); 80 | } 81 | pcs_destroy(pcs); 82 | } 83 | 84 | 85 | 你可以参考main.c,来获取更详细的使用示例。 86 | -------------------------------------------------------------------------------- /docs/如何编译为静态库.txt: -------------------------------------------------------------------------------- 1 | 在linux下编译静态库的方法: 2 | $>cd baidupcs/pcs 3 | $>make libpcs.a 4 | 5 | 使用方法: 6 | 1. 包含pcs_mem.h和pcs.h 7 | #include 8 | #include 9 | 10 | 2. 使用 pcs_create() 函数创建一个Pcs对象,使用完成后需使用pcs_destroy()来释放对象。 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/登录逻辑.txt: -------------------------------------------------------------------------------- 1 | 使用pcs_login登录时,可能需要输入验证码。 2 | pcs_login中检测到需要输入验证码时, 将会调用 PCS_OPTION_CAPTCHA_FUNCTION 设定的回调函数。 3 | 可以通过 pcs_setopt(pcs, PCS_OPTION_CAPTCHA_FUNCTION, cb_get_verify_code); 方法来设定验证码的输入逻辑。 4 | 5 | -------------------------------------------------------------------------------- /docs/目录结构.txt: -------------------------------------------------------------------------------- 1 | 目录结构描述如下: 2 | 3 | / 4 | |-baidupcs.sln (Microsoft Visual Studio 2012 解决方案,可以直接使用VS2012打开) 5 | |-README.md 6 | |-pcs (所有源代码在这个目录中) 7 | |-cJSON.c 8 | |-cJSON.h (cJSON是一个第三方开源的读取JSON的库) 9 | |-dir.c 10 | |-dir.h (本地文件相关函数:包含读取目录、设定最后修改时间等) 11 | |-hashtable.c 12 | |-hashtable.h (哈希表的C语言实现) 13 | |-main.c (包含入口函数、和quota,list,upload,download等子命令的实现) 14 | |-main_args.c 15 | |-main_args.h (使用argparser读取传入的参数) 16 | |-makefile (Makefile for Linux) 17 | |-makefile-cygwin (Makefile for cygwin) 18 | |-pcs.c 19 | |-pcs.h (百度网盘 API) 20 | |-pcs.vcxproj (VS2012的项目文件) 21 | |-pcs.vcxproj.filters (VS2012项目文件) 22 | |-pcs_cookie.c.del (已删除) 23 | |-pcs_cookie.h.del (已删除) 24 | |-pcs_defs.h (网盘API公用的定义) 25 | |-pcs_fileinfo.c 26 | |-pcs_fileinfo.h (定义了PcsFileInfo对象,和相关函数) 27 | |-pcs_http.c 28 | |-pcs_http.h (封装libcurl的方法,提供一些函数用于发送和接收http请求) 29 | |-pcs_io.c 30 | |-pcs_io.h (实现了和命令行交互的方法) 31 | |-pcs_list.c.del (已删除) 32 | |-pcs_list.h.del (已删除) 33 | |-pcs_mem.c 34 | |-pcs_mem.h (pcs_malloc,pcs_free等内存函数,定义_DEBUG宏时,实现内存泄漏检查) 35 | |-pcs_pan_api_resinfo.c 36 | |-pcs_pan_api_resinfo.h (定义了百度网盘filemanager的返回对象,及其相关函数) 37 | |-pcs_slist.c 38 | |-pcs_slist.h (定义了字符串链表,和相关函数) 39 | |-pcs_utils.c 40 | |-pcs_utils.h (定义了一些公用的工具函数) 41 | |-utf8.c 42 | |-utf8.h (一些和UTF8编码转换相关的函数) 43 | |-win32 (项目依赖项的WIN32版本) 44 | -------------------------------------------------------------------------------- /hashtable.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "pcs/pcs_mem.h" 6 | #include "hashtable.h" 7 | 8 | static unsigned int calcHash1(const char *key, int key_size, int ignore_case) 9 | { 10 | register unsigned int nr = 1, nr2 = 4, ch; 11 | int i; 12 | if (key_size == -1) key_size = strlen(key); 13 | for (i = 0; i < key_size; i++) { 14 | ch = (unsigned int)key[i]; 15 | if (ch >= 'A' && ch <= 'Z' && ignore_case && (i == 0 || !(key[i - 1] & 0x80))) 16 | ch += 'a' - 'A'; 17 | nr ^= (((nr & 63) + nr2) * ch) + (nr << 8); 18 | nr2 += 3; 19 | } 20 | return nr; 21 | } 22 | 23 | static unsigned int calcHash2(const char *key, int key_size, int ignore_case) 24 | { 25 | unsigned int hash = 0, ch; 26 | int i; 27 | if (key_size == -1) key_size = strlen(key); 28 | for (i = 0; i < key_size; i++) { 29 | ch = (unsigned int)key[i]; 30 | if (ch >= 'A' && ch <= 'Z' && ignore_case && (i == 0 || !(key[i - 1] & 0x80))) 31 | ch += 'a' - 'A'; 32 | hash *= 16777619; 33 | hash ^= ch; 34 | } 35 | return (hash); 36 | } 37 | 38 | static unsigned int calcHash3(const char *key, int key_size, int ignore_case) 39 | { 40 | unsigned int h, ch; 41 | int i; 42 | if (key_size == -1) key_size = strlen(key); 43 | for (h = 0, i = 0; i < key_size; i++) { 44 | ch = (unsigned int)key[i]; 45 | if (ch >= 'A' && ch <= 'Z' && ignore_case && (i == 0 || !(key[i - 1] & 0x80))) 46 | ch += 'a' - 'A'; 47 | h = 31 * h + (ch); 48 | } 49 | return h; 50 | } 51 | 52 | static HashtableNode *node_create(const char *key, int key_size, void *value, unsigned int hashA, unsigned int hashB) 53 | { 54 | HashtableNode *node; 55 | node = (HashtableNode *) pcs_malloc(sizeof(HashtableNode)); 56 | if (!node) 57 | return NULL; 58 | memset (node, 0, sizeof(HashtableNode)); 59 | if (key_size == -1) key_size = strlen(key); 60 | node->key = (char *)pcs_malloc(key_size + 1); 61 | if (!node->key) { 62 | pcs_free(node); 63 | return NULL; 64 | } 65 | memcpy(node->key, key, key_size); 66 | node->key[key_size] = '\0'; 67 | node->value = value; 68 | node->hashA = hashA; 69 | node->hashB = hashB; 70 | return node; 71 | } 72 | 73 | static void node_destroy(HashtableNode *node, void(*free_value)(void *)) 74 | { 75 | HashtableNode *tmp, *cusor; 76 | cusor = node; 77 | while(cusor) { 78 | tmp = cusor; 79 | cusor = cusor->next; 80 | if (tmp->key) 81 | pcs_free(tmp->key); 82 | if (free_value && tmp->value) 83 | (*free_value)(tmp->value); 84 | pcs_free(tmp); 85 | } 86 | } 87 | 88 | static int table_add_item(HashtableNode **table, int real_capacity, const char *key, int key_size, void *value, int ignore_case) 89 | { 90 | //不同的字符串三次hash还会碰撞的几率无限接近于不可能 91 | unsigned int nHash, nHashA, nHashB; 92 | unsigned int pos; 93 | HashtableNode *last = NULL, *p; 94 | if (key_size == -1) key_size = strlen(key); 95 | nHash = calcHash1(key, key_size, ignore_case); 96 | nHashA = calcHash2(key, key_size, ignore_case); 97 | nHashB = calcHash3(key, key_size, ignore_case); 98 | pos = nHash % real_capacity; 99 | p = table[pos]; 100 | if (!p) { 101 | table[pos] = node_create(key, key_size, value, nHashA, nHashB); 102 | if (!table[pos]) 103 | return -1; 104 | return 0; 105 | } 106 | while (p) { 107 | if (p->hashA == nHashA && p->hashB == nHashB) { 108 | break; 109 | } 110 | last = p; 111 | p = p->next; 112 | } 113 | if (p) { 114 | return -1; 115 | } 116 | else { 117 | p = node_create(key, key_size, value, nHashA, nHashB); 118 | if (!p) 119 | return -1; 120 | last->next = p; 121 | } 122 | return 0; 123 | } 124 | 125 | static int table_set_item(HashtableNode **table, int real_capacity, const char *key, int key_size, void *value, int ignore_case, int *pHasOld, void **pOldVal) 126 | { 127 | //不同的字符串三次hash还会碰撞的几率无限接近于不可能 128 | unsigned int nHash, nHashA, nHashB; 129 | unsigned int pos; 130 | HashtableNode *last = NULL, *p; 131 | if (key_size == -1) key_size = strlen(key); 132 | nHash = calcHash1(key, key_size, ignore_case); 133 | nHashA = calcHash2(key, key_size, ignore_case); 134 | nHashB = calcHash3(key, key_size, ignore_case); 135 | pos = nHash % real_capacity; 136 | p = table[pos]; 137 | if (pHasOld) (*pHasOld) = 0; 138 | if (!p) { 139 | table[pos] = node_create(key, key_size, value, nHashA, nHashB); 140 | if (!table[pos]) return -1; 141 | return 0; 142 | } 143 | while (p) { 144 | if (p->hashA == nHashA && p->hashB == nHashB) { 145 | break; 146 | } 147 | last = p; 148 | p = p->next; 149 | } 150 | if (p) { 151 | if (pHasOld) (*pHasOld) = 1; 152 | if (pOldVal) (*pOldVal) = p->value; 153 | //p->key = key; 154 | p->value = value; 155 | return 0; 156 | } 157 | else { 158 | p = node_create(key, key_size, value, nHashA, nHashB); 159 | if (!p) return -1; 160 | last->next = p; 161 | } 162 | return 0; 163 | } 164 | 165 | static HashtableNode *table_get_item(HashtableNode **table, int real_capacity, const char *key, int key_size, int ignore_case) 166 | { 167 | unsigned int nHash, nHashA, nHashB; 168 | unsigned int pos; 169 | HashtableNode *p; 170 | if (key_size == -1) key_size = strlen(key); 171 | nHash = calcHash1(key, key_size, ignore_case); 172 | pos = nHash % real_capacity; 173 | p = table[pos]; 174 | if (!p) return NULL; 175 | nHashA = calcHash2(key, key_size, ignore_case); 176 | nHashB = calcHash3(key, key_size, ignore_case); 177 | while (p) { 178 | if (p->hashA == nHashA && p->hashB == nHashB) { 179 | break; 180 | } 181 | p = p->next; 182 | } 183 | return p; 184 | } 185 | 186 | static HashtableNode *table_remove_item(HashtableNode **table, int real_capacity, const char *key, int key_size, int ignore_case) 187 | { 188 | unsigned int nHash, nHashA, nHashB; 189 | unsigned int pos; 190 | HashtableNode *p, *prev = NULL; 191 | if (key_size == -1) key_size = strlen(key); 192 | nHash = calcHash1(key, key_size, ignore_case); 193 | pos = nHash % real_capacity; 194 | p = table[pos]; 195 | if (p) { 196 | nHashA = calcHash2(key, key_size, ignore_case); 197 | nHashB = calcHash3(key, key_size, ignore_case); 198 | while (p) { 199 | if (p->hashA == nHashA && p->hashB == nHashB) { 200 | break; 201 | } 202 | prev = p; 203 | p = p->next; 204 | } 205 | if (p) { 206 | if (prev) { 207 | prev->next = p->next; 208 | } 209 | else { 210 | table[pos] = p->next; 211 | } 212 | p->next = NULL; 213 | } 214 | } 215 | return p; 216 | } 217 | 218 | static void table_clear(HashtableNode **table, int real_capacity, void(*free_value)(void *)) 219 | { 220 | int i; 221 | HashtableNode *node; 222 | for(i = 0; i < real_capacity; i++) { 223 | node = table[i]; 224 | node_destroy(node, free_value); 225 | table[i] = NULL; 226 | } 227 | } 228 | 229 | static void table_destroy(HashtableNode **table, int real_capacity, void(*free_value)(void *)) 230 | { 231 | table_clear(table, real_capacity, free_value); 232 | pcs_free(table); 233 | } 234 | 235 | Hashtable *ht_create(int capacity, int ignore_case, void (*free_value)(void *)) 236 | { 237 | Hashtable *ht; 238 | ht = (Hashtable *) pcs_malloc(sizeof(Hashtable)); 239 | if (!ht) 240 | return NULL; 241 | memset (ht, 0, sizeof(Hashtable)); 242 | if (capacity < 17) capacity = 17; 243 | ht->capacity = capacity; 244 | ht->real_capacity = (int)(ht->capacity * HASH_EXTEND_MULTIPLIER); 245 | ht->count = 0; 246 | ht->free_value = free_value; 247 | ht->table = (HashtableNode **)pcs_malloc(ht->real_capacity * sizeof(HashtableNode *)); 248 | if (!ht->table) { 249 | pcs_free(ht); 250 | return NULL; 251 | } 252 | memset (ht->table, 0, ht->real_capacity * sizeof(HashtableNode *)); 253 | ht->ignore_case = ignore_case; 254 | return ht; 255 | } 256 | 257 | void ht_destroy(Hashtable *ht) 258 | { 259 | table_destroy(ht->table, ht->real_capacity, ht->free_value); 260 | pcs_free(ht); 261 | } 262 | 263 | int ht_expand(Hashtable *ht, int capacity) 264 | { 265 | HashtableNode **table, *node; 266 | int real_capacity, i, cnt; 267 | real_capacity = (int)(capacity * HASH_EXTEND_MULTIPLIER); 268 | table = (HashtableNode **)pcs_malloc(real_capacity * sizeof(HashtableNode *)); 269 | if (!table) { 270 | return -1; 271 | } 272 | memset (table, 0, real_capacity * sizeof(HashtableNode *)); 273 | cnt = 0; 274 | for(i = 0; i < ht->real_capacity; i++) { 275 | node = ht->table[i]; 276 | while(node) { 277 | if (table_add_item(table, real_capacity, node->key, -1, node->value, ht->ignore_case)) { 278 | table_destroy(table, real_capacity, NULL); 279 | return -1; 280 | } 281 | cnt++; 282 | node = node->next; 283 | } 284 | } 285 | table_destroy(ht->table, ht->real_capacity, NULL); 286 | ht->table = table; 287 | ht->capacity = capacity; 288 | ht->real_capacity = real_capacity; 289 | ht->count = cnt; 290 | return 0; 291 | } 292 | 293 | int ht_add(Hashtable *ht, const char *key, int key_size, void *value) 294 | { 295 | if (ht->count >= ht->capacity) { 296 | if (ht_expand(ht, ht->count * 2)) 297 | return -1; 298 | } 299 | if (table_add_item(ht->table, ht->real_capacity, key, key_size, value, ht->ignore_case)) 300 | return -1; 301 | ht->count++; 302 | return 0; 303 | } 304 | 305 | int ht_set(Hashtable *ht, const char *key, int key_size, void *value, void **pOldVal) 306 | { 307 | void *oldVal = NULL; 308 | int rc, pHasOld; 309 | rc = table_set_item(ht->table, ht->real_capacity, key, key_size, value, ht->ignore_case, &pHasOld, pOldVal ? pOldVal : &oldVal); 310 | if (oldVal && ht->free_value) (*ht->free_value)(oldVal); /*如果pOldVal传入NULL,且有旧值时,自动释放*/ 311 | if (!pHasOld) ht->count++; 312 | return rc; 313 | } 314 | 315 | int ht_remove(Hashtable *ht, const char *key, int key_size, void **pVal) 316 | { 317 | HashtableNode *p; 318 | p = table_remove_item(ht->table, ht->real_capacity, key, key_size, ht->ignore_case); 319 | if (p) { 320 | if (pVal) *pVal = p->value; 321 | node_destroy(p, pVal ? NULL : ht->free_value); 322 | ht->count--; 323 | return 0; 324 | } 325 | return -1; 326 | } 327 | 328 | void *ht_get(Hashtable *ht, const char *key, int key_size) 329 | { 330 | HashtableNode *p; 331 | p = table_get_item(ht->table, ht->real_capacity, key, key_size, ht->ignore_case); 332 | if (!p) 333 | return NULL; 334 | return p->value; 335 | } 336 | 337 | HashtableNode *ht_get_node(Hashtable *ht, const char *key, int key_size) 338 | { 339 | return table_get_item(ht->table, ht->real_capacity, key, key_size, ht->ignore_case); 340 | } 341 | 342 | int ht_has(Hashtable *ht, const char *key, int key_size) 343 | { 344 | HashtableNode *p; 345 | p = table_get_item(ht->table, ht->real_capacity, key, key_size, ht->ignore_case); 346 | return (p ? 1 : 0); 347 | } 348 | 349 | int ht_clear(Hashtable *ht) 350 | { 351 | table_clear(ht->table, ht->real_capacity, ht->free_value); 352 | ht->count = 0; 353 | return 0; 354 | } 355 | 356 | HashtableIterater *ht_it_create(Hashtable *ht) 357 | { 358 | HashtableIterater *iterater; 359 | iterater = (HashtableIterater *) pcs_malloc(sizeof(HashtableIterater)); 360 | if (!iterater) 361 | return NULL; 362 | memset(iterater, 0, sizeof(HashtableIterater)); 363 | iterater->ht = ht; 364 | iterater->index = -1; 365 | return iterater; 366 | } 367 | 368 | void ht_it_destroy(HashtableIterater *iterater) 369 | { 370 | pcs_free(iterater); 371 | } 372 | 373 | void ht_it_reset(HashtableIterater *iterater) 374 | { 375 | iterater->index = -1; 376 | } 377 | 378 | int ht_it_next(HashtableIterater *iterater) 379 | { 380 | if (iterater->ht->count == 0) 381 | return 0; 382 | if (iterater->p) { 383 | iterater->p = iterater->p->next; 384 | if (iterater->p) 385 | return 1; 386 | } 387 | if (iterater->index >= iterater->ht->real_capacity) 388 | return 0; 389 | iterater->index++; 390 | 391 | while(iterater->index < iterater->ht->real_capacity) { 392 | iterater->p = iterater->ht->table[iterater->index]; 393 | if (iterater->p) 394 | break; 395 | iterater->index++; 396 | } 397 | if (iterater->p) 398 | return 1; 399 | return 0; 400 | } 401 | 402 | void *ht_it_current(HashtableIterater *iterater) 403 | { 404 | if (iterater->p) 405 | return iterater->p->value; 406 | return NULL; 407 | } 408 | 409 | -------------------------------------------------------------------------------- /hashtable.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_SHELL_HASHTABLE_H_ 2 | #define _PCS_SHELL_HASHTABLE_H_ 3 | 4 | #ifndef HASH_EXTEND_MULTIPLIER 5 | #define HASH_EXTEND_MULTIPLIER ( 1.75F ) 6 | #endif 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | 13 | typedef struct HashtableNode HashtableNode; 14 | struct HashtableNode { 15 | char *key; 16 | unsigned int hashA; 17 | unsigned int hashB; 18 | void *value; 19 | HashtableNode *next; 20 | }; 21 | 22 | typedef struct Hashtable Hashtable; 23 | struct Hashtable { 24 | int capacity; 25 | int real_capacity; 26 | int count; 27 | HashtableNode **table; 28 | void (*free_value)(void *); 29 | int ignore_case; 30 | }; 31 | 32 | typedef struct HashtableIterater { 33 | Hashtable *ht; 34 | int index; 35 | HashtableNode *p; 36 | } HashtableIterater; 37 | 38 | /* 39 | * 创建一个哈希表 40 | * capacity 的最大容量,即内部节点表格的元素数量 41 | * ignore_case - Key是否忽略大小写。0-表示不忽略;非0值表示忽略大小写 42 | * free_value - 一个函数,清空哈希表时,将使用每一个节点的value值来调用该函数 43 | */ 44 | Hashtable *ht_create(int capacity, int ignore_case, void (*free_value)(void *)); 45 | /*释放掉哈希表*/ 46 | void ht_destroy(Hashtable *ht); 47 | /*扩容哈希表。成功返回0,失败返回非0值。*/ 48 | int ht_expand(Hashtable *ht, int capacity); 49 | /* 50 | 添加一项到哈希表中。 51 | key_size 传入-1时,自动使用strlen()计算 52 | 如果失败或已经存在,则返回非0值,否则返回0 53 | */ 54 | int ht_add(Hashtable *ht, const char *key, int key_size, void *value); 55 | /*设置一个项的值, 56 | * 如果key已经存在,则修改其值为value,并设定(*pOldVal)为旧值, 57 | * 如果key不存在,则添加一个新项,不设置(*pOldVal)的值。 58 | * 如果不需要接收旧值,设置 pOldVal 的值为 NULL。 59 | * 如果失败,则返回非0值,否则返回0 60 | */ 61 | int ht_set(Hashtable *ht, const char *key, int key_size, void *value, void **pOldVal); 62 | /* 63 | * 从哈希表中移除一项。如果失败或不存在,则返回非0值,否则返回0。 64 | * 如果 pVal 值不为NULL,函数执行成功时,将把被移除项的value值写入pVal指定的地址中。 65 | * 如果不需要接收被移除项的值,设置 pVal 的值为 NULL。 66 | */ 67 | int ht_remove(Hashtable *ht, const char *key, int key_size, void **pVal); 68 | /*返回哈希表中是否存在该项。不存在返回0,存在返回1。*/ 69 | int ht_has(Hashtable *ht, const char *key, int key_size); 70 | /*返回哈希表中key指定项的值。如果不存在则返回NULL,存在则返回实际值*/ 71 | void *ht_get(Hashtable *ht, const char *key, int key_size); 72 | /*返回哈希表中key指定的节点项。如果不存在则返回NULL,存在则返回该节点*/ 73 | HashtableNode *ht_get_node(Hashtable *ht, const char *key, int key_size); 74 | /*清空哈希表。注意函数不会自动释放每项的值,清空前需迭代每一项来释放其值。*/ 75 | int ht_clear(Hashtable *ht); 76 | 77 | /*创建一个哈希表的迭代器*/ 78 | HashtableIterater *ht_it_create(Hashtable *ht); 79 | /*释放迭代器*/ 80 | void ht_it_destroy(HashtableIterater *iterater); 81 | /*重置迭代器*/ 82 | void ht_it_reset(HashtableIterater *iterater); 83 | /*迭代器移动到下一条。移动成功则返回1,否则返回0*/ 84 | int ht_it_next(HashtableIterater *iterater); 85 | /*返回迭代器当前项的值*/ 86 | void *ht_it_current(HashtableIterater *iterater); 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GangZhuo/BaiduPCS/04b575f95aed22fd30e8b093364cddd7fbf48e2b/m4/.gitignore -------------------------------------------------------------------------------- /m4/ax_check_openssl.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Look for OpenSSL in a number of default spots, or in a user-selected 12 | # spot (via --with-openssl). Sets 13 | # 14 | # OPENSSL_INCLUDES to the include directives required 15 | # OPENSSL_LIBS to the -l directives required 16 | # OPENSSL_LDFLAGS to the -L or -R flags required 17 | # 18 | # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately 19 | # 20 | # This macro sets OPENSSL_INCLUDES such that source files should use the 21 | # openssl/ directory in include directives: 22 | # 23 | # #include 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2009,2010 Zmanda Inc. 28 | # Copyright (c) 2009,2010 Dustin J. Mitchell 29 | # 30 | # Copying and distribution of this file, with or without modification, are 31 | # permitted in any medium without royalty provided the copyright notice 32 | # and this notice are preserved. This file is offered as-is, without any 33 | # warranty. 34 | 35 | #serial 9 36 | 37 | AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) 38 | AC_DEFUN([AX_CHECK_OPENSSL], [ 39 | found=false 40 | AC_ARG_WITH([openssl], 41 | [AS_HELP_STRING([--with-openssl=DIR], 42 | [root of the OpenSSL directory])], 43 | [ 44 | case "$withval" in 45 | "" | y | ye | yes | n | no) 46 | AC_MSG_ERROR([Invalid --with-openssl value]) 47 | ;; 48 | *) ssldirs="$withval" 49 | ;; 50 | esac 51 | ], [ 52 | # if pkg-config is installed and openssl has installed a .pc file, 53 | # then use that information and don't search ssldirs 54 | AC_CHECK_TOOL([PKG_CONFIG], [pkg-config]) 55 | if test x"$PKG_CONFIG" != x""; then 56 | OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` 57 | if test $? = 0; then 58 | OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` 59 | OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` 60 | found=true 61 | fi 62 | fi 63 | 64 | # no such luck; use some default ssldirs 65 | if ! $found; then 66 | ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" 67 | fi 68 | ] 69 | ) 70 | 71 | 72 | # note that we #include , so the OpenSSL headers have to be in 73 | # an 'openssl' subdirectory 74 | 75 | if ! $found; then 76 | OPENSSL_INCLUDES= 77 | for ssldir in $ssldirs; do 78 | AC_MSG_CHECKING([for openssl/ssl.h in $ssldir]) 79 | if test -f "$ssldir/include/openssl/ssl.h"; then 80 | OPENSSL_INCLUDES="-I$ssldir/include" 81 | OPENSSL_LDFLAGS="-L$ssldir/lib" 82 | OPENSSL_LIBS="-lssl -lcrypto" 83 | found=true 84 | AC_MSG_RESULT([yes]) 85 | break 86 | else 87 | AC_MSG_RESULT([no]) 88 | fi 89 | done 90 | 91 | # if the file wasn't found, well, go ahead and try the link anyway -- maybe 92 | # it will just work! 93 | fi 94 | 95 | # try the preprocessor and linker with our new flags, 96 | # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS 97 | 98 | AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) 99 | echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ 100 | "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD 101 | 102 | save_LIBS="$LIBS" 103 | save_LDFLAGS="$LDFLAGS" 104 | save_CPPFLAGS="$CPPFLAGS" 105 | LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" 106 | LIBS="$OPENSSL_LIBS $LIBS" 107 | CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" 108 | AC_LINK_IFELSE( 109 | [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], 110 | [ 111 | AC_MSG_RESULT([yes]) 112 | $1 113 | ], [ 114 | AC_MSG_RESULT([no]) 115 | $2 116 | ]) 117 | CPPFLAGS="$save_CPPFLAGS" 118 | LDFLAGS="$save_LDFLAGS" 119 | LIBS="$save_LIBS" 120 | 121 | AC_SUBST([OPENSSL_INCLUDES]) 122 | AC_SUBST([OPENSSL_LIBS]) 123 | AC_SUBST([OPENSSL_LDFLAGS]) 124 | ]) 125 | -------------------------------------------------------------------------------- /m4/ax_lib_crypto.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_lib_crypto.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_LIB_CRYPTO([yes|no|auto]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Searches for the 'crypto' library with the --with... option. 12 | # 13 | # If found, define HAVE_CRYPTO and macro CRYPTO_LIBS. Also defines 14 | # CRYPTO_WITH_ for the algorithms found available. Possible 15 | # algorithms: AES BF CAMELLIA CAST DES IDEA RC2 RC5 MD2 MD4 MD5 SHA RIPEMD 16 | # RSA DSA DH 17 | # 18 | # The argument is used if no --with...-crypto option is set. Value "yes" 19 | # requires the configuration by default. Value "no" does not require it by 20 | # default. Value "auto" configures the library only if available. 21 | # 22 | # See also AX_LIB_BEECRYPT and AX_LIB_GCRYPT. 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2009 Fabien Coelho 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 7 34 | 35 | # AX_CHECK_CRYPTO_LIB([algo-name],[function]) 36 | AC_DEFUN([AX_CHECK_CRYPTO_LIB],[ 37 | AC_CHECK_LIB([crypto], $2, [ 38 | AC_DEFINE([CRYPTO_WITH_$1],[1],[Algorithm $1 in openssl crypto library]) 39 | ]) 40 | ]) 41 | 42 | # AX_LIB_CRYPTO([yes|no|auto]) 43 | AC_DEFUN([AX_LIB_CRYPTO],[ 44 | AC_MSG_CHECKING([whether openssl crypto is enabled]) 45 | AC_ARG_WITH([crypto],[ --with-crypto requite crypto library 46 | --without-crypto disable crypto library],[ 47 | AC_MSG_RESULT([$withval]) 48 | ac_with_crypto=$withval 49 | ],[ 50 | AC_MSG_RESULT([$1]) 51 | ac_with_crypto=$1 52 | ]) 53 | if test "$ac_with_crypto" = "yes" -o "$ac_with_crypto" = "auto" ; then 54 | AC_CHECK_HEADERS([openssl/opensslconf.h],[ 55 | AC_CHECK_LIB([crypto], [CRYPTO_lock],[ 56 | AC_DEFINE([HAVE_CRYPTO],[1],[Openssl crypto library is available]) 57 | HAVE_CRYPTO=1 58 | AC_SUBST([CRYPTO_LIBS],[-lcrypto]) 59 | # ciphers 60 | AX_CHECK_CRYPTO_LIB([AES],[AES_ecb_encrypt]) 61 | AX_CHECK_CRYPTO_LIB([BF],[BF_ecb_encrypt]) 62 | AX_CHECK_CRYPTO_LIB([CAST],[CAST_ecb_encrypt]) 63 | AX_CHECK_CRYPTO_LIB([CAMELLIA],[Camellia_ecb_encrypt]) 64 | AX_CHECK_CRYPTO_LIB([DES],[DES_ecb_encrypt]) 65 | AX_CHECK_CRYPTO_LIB([IDEA],[idea_ecb_encrypt]) 66 | AX_CHECK_CRYPTO_LIB([RC2],[RC2_ecb_encrypt]) 67 | AX_CHECK_CRYPTO_LIB([RC5],[RC5_32_ecb_encrypt]) 68 | # digests 69 | AX_CHECK_CRYPTO_LIB([MD2],[MD2]) 70 | AX_CHECK_CRYPTO_LIB([MD4],[MD4]) 71 | AX_CHECK_CRYPTO_LIB([MD5],[MD5]) 72 | AX_CHECK_CRYPTO_LIB([RIPEMD],[RIPEMD160]) 73 | AX_CHECK_CRYPTO_LIB([SHA],[SHA1]) 74 | # others 75 | AX_CHECK_CRYPTO_LIB([RSA],[RSA_set_method]) 76 | AX_CHECK_CRYPTO_LIB([DSA],[DSA_set_method]) 77 | AX_CHECK_CRYPTO_LIB([DH],[DH_set_method]) 78 | ]) 79 | ]) 80 | # complain only if crypto as *explicitely* required 81 | if test "$ac_with_crypto" = "yes" -a "x$HAVE_CRYPTO" = "x" ; then 82 | AC_MSG_ERROR([cannot configure required openssl crypto library]) 83 | fi 84 | fi 85 | ]) 86 | -------------------------------------------------------------------------------- /m4/ltsugar.m4: -------------------------------------------------------------------------------- 1 | # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software 4 | # Foundation, Inc. 5 | # Written by Gary V. Vaughan, 2004 6 | # 7 | # This file is free software; the Free Software Foundation gives 8 | # unlimited permission to copy and/or distribute it, with or without 9 | # modifications, as long as this notice is preserved. 10 | 11 | # serial 6 ltsugar.m4 12 | 13 | # This is to help aclocal find these macros, as it can't see m4_define. 14 | AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) 15 | 16 | 17 | # lt_join(SEP, ARG1, [ARG2...]) 18 | # ----------------------------- 19 | # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their 20 | # associated separator. 21 | # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier 22 | # versions in m4sugar had bugs. 23 | m4_define([lt_join], 24 | [m4_if([$#], [1], [], 25 | [$#], [2], [[$2]], 26 | [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) 27 | m4_define([_lt_join], 28 | [m4_if([$#$2], [2], [], 29 | [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) 30 | 31 | 32 | # lt_car(LIST) 33 | # lt_cdr(LIST) 34 | # ------------ 35 | # Manipulate m4 lists. 36 | # These macros are necessary as long as will still need to support 37 | # Autoconf-2.59, which quotes differently. 38 | m4_define([lt_car], [[$1]]) 39 | m4_define([lt_cdr], 40 | [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], 41 | [$#], 1, [], 42 | [m4_dquote(m4_shift($@))])]) 43 | m4_define([lt_unquote], $1) 44 | 45 | 46 | # lt_append(MACRO-NAME, STRING, [SEPARATOR]) 47 | # ------------------------------------------ 48 | # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. 49 | # Note that neither SEPARATOR nor STRING are expanded; they are appended 50 | # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). 51 | # No SEPARATOR is output if MACRO-NAME was previously undefined (different 52 | # than defined and empty). 53 | # 54 | # This macro is needed until we can rely on Autoconf 2.62, since earlier 55 | # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. 56 | m4_define([lt_append], 57 | [m4_define([$1], 58 | m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) 59 | 60 | 61 | 62 | # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) 63 | # ---------------------------------------------------------- 64 | # Produce a SEP delimited list of all paired combinations of elements of 65 | # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list 66 | # has the form PREFIXmINFIXSUFFIXn. 67 | # Needed until we can rely on m4_combine added in Autoconf 2.62. 68 | m4_define([lt_combine], 69 | [m4_if(m4_eval([$# > 3]), [1], 70 | [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl 71 | [[m4_foreach([_Lt_prefix], [$2], 72 | [m4_foreach([_Lt_suffix], 73 | ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, 74 | [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) 75 | 76 | 77 | # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) 78 | # ----------------------------------------------------------------------- 79 | # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited 80 | # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. 81 | m4_define([lt_if_append_uniq], 82 | [m4_ifdef([$1], 83 | [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], 84 | [lt_append([$1], [$2], [$3])$4], 85 | [$5])], 86 | [lt_append([$1], [$2], [$3])$4])]) 87 | 88 | 89 | # lt_dict_add(DICT, KEY, VALUE) 90 | # ----------------------------- 91 | m4_define([lt_dict_add], 92 | [m4_define([$1($2)], [$3])]) 93 | 94 | 95 | # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) 96 | # -------------------------------------------- 97 | m4_define([lt_dict_add_subkey], 98 | [m4_define([$1($2:$3)], [$4])]) 99 | 100 | 101 | # lt_dict_fetch(DICT, KEY, [SUBKEY]) 102 | # ---------------------------------- 103 | m4_define([lt_dict_fetch], 104 | [m4_ifval([$3], 105 | m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), 106 | m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) 107 | 108 | 109 | # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) 110 | # ----------------------------------------------------------------- 111 | m4_define([lt_if_dict_fetch], 112 | [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], 113 | [$5], 114 | [$6])]) 115 | 116 | 117 | # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) 118 | # -------------------------------------------------------------- 119 | m4_define([lt_dict_filter], 120 | [m4_if([$5], [], [], 121 | [lt_join(m4_quote(m4_default([$4], [[, ]])), 122 | lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), 123 | [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl 124 | ]) 125 | -------------------------------------------------------------------------------- /m4/ltversion.m4: -------------------------------------------------------------------------------- 1 | # ltversion.m4 -- version numbers -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # @configure_input@ 11 | 12 | # serial 4179 ltversion.m4 13 | # This file is part of GNU Libtool 14 | 15 | m4_define([LT_PACKAGE_VERSION], [2.4.6]) 16 | m4_define([LT_PACKAGE_REVISION], [2.4.6]) 17 | 18 | AC_DEFUN([LTVERSION_VERSION], 19 | [macro_version='2.4.6' 20 | macro_revision='2.4.6' 21 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) 22 | _LT_DECL(, macro_revision, 0) 23 | ]) 24 | -------------------------------------------------------------------------------- /m4/lt~obsolete.m4: -------------------------------------------------------------------------------- 1 | # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software 4 | # Foundation, Inc. 5 | # Written by Scott James Remnant, 2004. 6 | # 7 | # This file is free software; the Free Software Foundation gives 8 | # unlimited permission to copy and/or distribute it, with or without 9 | # modifications, as long as this notice is preserved. 10 | 11 | # serial 5 lt~obsolete.m4 12 | 13 | # These exist entirely to fool aclocal when bootstrapping libtool. 14 | # 15 | # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), 16 | # which have later been changed to m4_define as they aren't part of the 17 | # exported API, or moved to Autoconf or Automake where they belong. 18 | # 19 | # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN 20 | # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us 21 | # using a macro with the same name in our local m4/libtool.m4 it'll 22 | # pull the old libtool.m4 in (it doesn't see our shiny new m4_define 23 | # and doesn't know about Autoconf macros at all.) 24 | # 25 | # So we provide this file, which has a silly filename so it's always 26 | # included after everything else. This provides aclocal with the 27 | # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything 28 | # because those macros already exist, or will be overwritten later. 29 | # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 30 | # 31 | # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. 32 | # Yes, that means every name once taken will need to remain here until 33 | # we give up compatibility with versions before 1.7, at which point 34 | # we need to keep only those names which we still refer to. 35 | 36 | # This is to help aclocal find these macros, as it can't see m4_define. 37 | AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) 38 | 39 | m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) 40 | m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) 41 | m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) 42 | m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) 43 | m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) 44 | m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) 45 | m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) 46 | m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) 47 | m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) 48 | m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) 49 | m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) 50 | m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) 51 | m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) 52 | m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) 53 | m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) 54 | m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) 55 | m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) 56 | m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) 57 | m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) 58 | m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) 59 | m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) 60 | m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) 61 | m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) 62 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) 63 | m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) 64 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) 65 | m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) 66 | m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) 67 | m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) 68 | m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) 69 | m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) 70 | m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) 71 | m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) 72 | m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) 73 | m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) 74 | m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) 75 | m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) 76 | m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) 77 | m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) 78 | m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) 79 | m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) 80 | m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) 81 | m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) 82 | m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) 83 | m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) 84 | m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) 85 | m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) 86 | m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) 87 | m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) 88 | m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) 89 | m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) 90 | m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) 91 | m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) 92 | m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) 93 | m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) 94 | m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) 95 | m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) 96 | m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) 97 | m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) 98 | m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) 99 | m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) 100 | -------------------------------------------------------------------------------- /openwrt/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/rules.mk 2 | 3 | PKG_NAME:=BaiduPCS 4 | PKG_VERSION:=0.3 5 | PKG_RELEASE:=$(PKG_SOURCE_VERSION) 6 | 7 | PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) 8 | #PKG_SOURCE_URL:=https://github.com/GangZhuo/BaiduPCS/archive 9 | #PKG_SOURCE:=$(PKG_VERSION).tar.gz 10 | PKG_BUILD_DEPENDS:=libopenssl libcurl libpthread 11 | 12 | #PKG_INSTALL:=1 13 | 14 | include $(INCLUDE_DIR)/package.mk 15 | 16 | define Package/BaiduPCS 17 | SECTION:=utils 18 | CATEGORY:=Utilities 19 | TITLE:=BaiduPCS 20 | URL:=https://github.com/GangZhuo/BaiduPCS 21 | MAINTAINER:=Gang Zhuo 22 | DEPENDS:=+libopenssl +libcurl +libpthread 23 | endef 24 | 25 | define Package/BaiduPCS/description 26 | The client for baidu net disk. 27 | endef 28 | 29 | define Build/Prepare 30 | mkdir -p $(PKG_BUILD_DIR) 31 | cp -r ../* $(PKG_BUILD_DIR) 32 | endef 33 | 34 | define Package/BaiduPCS/install 35 | $(INSTALL_DIR) $(1)/usr/bin 36 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/pcs $(1)/usr/bin 37 | endef 38 | 39 | $(eval $(call BuildPackage,BaiduPCS)) 40 | -------------------------------------------------------------------------------- /pcs/BaiduPCS.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_BAIDUPCS_H 2 | #define _PCS_BAIDUPCS_H 3 | 4 | #define PCS_IMPORT_LIB 5 | #include "pcs.h" 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /pcs/BaiduPCS_DLL.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {6EDC18B3-E237-4C73-9A54-58B0BEB98998} 15 | Win32Proj 16 | BaiduPCS 17 | BaiduPCS_DLL 18 | 8.1 19 | 20 | 21 | 22 | DynamicLibrary 23 | true 24 | v140_xp 25 | NotSet 26 | 27 | 28 | DynamicLibrary 29 | false 30 | v140_xp 31 | true 32 | NotSet 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | true 46 | BaiduPCS 47 | .dll 48 | 49 | 50 | false 51 | BaiduPCS 52 | .dll 53 | 54 | 55 | 56 | NotUsing 57 | Level3 58 | Disabled 59 | WIN32;_DEBUG;_WINDOWS;_USRDLL;BAIDUPCS_EXPORTS;PCS_STATIC_LIB;CURL_STATICLIB;LIBCONFIG_STATIC;PCRE_STATIC;_CRT_SECURE_NO_WARNINGS;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) 60 | $(SolutionDir)deps\include;%(AdditionalIncludeDirectories) 61 | MultiThreadedDLL 62 | /utf-8 %(AdditionalOptions) 63 | 64 | 65 | Windows 66 | true 67 | $(SolutionDir)deps\lib\$(PlatformTarget);%(AdditionalLibraryDirectories) 68 | libcurl_a.lib;%(AdditionalDependencies) 69 | libcmt.lib 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Level3 79 | NotUsing 80 | MaxSpeed 81 | true 82 | true 83 | WIN32;NDEBUG;_WINDOWS;_USRDLL;BAIDUPCS_EXPORTS;PCS_STATIC_LIB;CURL_STATICLIB;LIBCONFIG_STATIC;PCRE_STATIC;_CRT_SECURE_NO_WARNINGS;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) 84 | $(SolutionDir)deps\include;%(AdditionalIncludeDirectories) 85 | MultiThreadedDLL 86 | /utf-8 %(AdditionalOptions) 87 | 88 | 89 | Windows 90 | true 91 | true 92 | true 93 | $(SolutionDir)deps\lib\$(PlatformTarget);%(AdditionalLibraryDirectories) 94 | libcurl_a.lib;%(AdditionalDependencies) 95 | libcmt.lib 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /pcs/BaiduPCS_DLL.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | 68 | 69 | Source Files 70 | 71 | 72 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | Source Files 79 | 80 | 81 | Source Files 82 | 83 | 84 | Source Files 85 | 86 | 87 | Source Files 88 | 89 | 90 | Source Files 91 | 92 | 93 | Source Files 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files 106 | 107 | 108 | -------------------------------------------------------------------------------- /pcs/cJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef cJSON__h 24 | #define cJSON__h 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | /* cJSON Types: */ 32 | #define cJSON_False 0 33 | #define cJSON_True 1 34 | #define cJSON_NULL 2 35 | #define cJSON_Number 3 36 | #define cJSON_String 4 37 | #define cJSON_Array 5 38 | #define cJSON_Object 6 39 | 40 | #define cJSON_IsReference 256 41 | 42 | /* The cJSON structure: */ 43 | typedef struct cJSON { 44 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 45 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 46 | 47 | int type; /* The type of the item, as above. */ 48 | 49 | char *valuestring; /* The item's string, if type==cJSON_String */ 50 | int valueint; /* The item's number, if type==cJSON_Number */ 51 | int valueuint; /* The item's number, if type==cJSON_Number */ 52 | double valuedouble; /* The item's number, if type==cJSON_Number */ 53 | 54 | char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 55 | } cJSON; 56 | 57 | typedef struct cJSON_Hooks { 58 | void *(*malloc_fn)(size_t sz); 59 | void (*free_fn)(void *ptr); 60 | } cJSON_Hooks; 61 | 62 | /* Supply malloc, realloc and free functions to cJSON */ 63 | extern void cJSON_InitHooks(cJSON_Hooks* hooks); 64 | 65 | 66 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ 67 | extern cJSON *cJSON_Parse(const char *value); 68 | /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ 69 | extern char *cJSON_Print(cJSON *item); 70 | /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ 71 | extern char *cJSON_PrintUnformatted(cJSON *item); 72 | /* Delete a cJSON entity and all subentities. */ 73 | extern void cJSON_Delete(cJSON *c); 74 | 75 | /* Returns the number of items in an array (or object). */ 76 | extern int cJSON_GetArraySize(cJSON *array); 77 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 78 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 79 | /* Get item "string" from object. Case insensitive. */ 80 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 81 | 82 | /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ 83 | extern const char *cJSON_GetErrorPtr(void); 84 | 85 | /* These calls create a cJSON item of the appropriate type. */ 86 | extern cJSON *cJSON_CreateNull(void); 87 | extern cJSON *cJSON_CreateTrue(void); 88 | extern cJSON *cJSON_CreateFalse(void); 89 | extern cJSON *cJSON_CreateBool(int b); 90 | extern cJSON *cJSON_CreateNumber(double num); 91 | extern cJSON *cJSON_CreateString(const char *string); 92 | extern cJSON *cJSON_CreateArray(void); 93 | extern cJSON *cJSON_CreateObject(void); 94 | 95 | /* These utilities create an Array of count items. */ 96 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 97 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 98 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 99 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 100 | 101 | /* Append item to the specified array/object. */ 102 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 103 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 104 | /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ 105 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 106 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 107 | 108 | /* Remove/Detatch items from Arrays/Objects. */ 109 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 110 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 111 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 112 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 113 | 114 | /* Update array items. */ 115 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 116 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 117 | 118 | /* Duplicate a cJSON item */ 119 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 120 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 121 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 122 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 123 | 124 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 125 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 126 | 127 | extern void cJSON_Minify(char *json); 128 | 129 | /* Macros for creating things quickly. */ 130 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 131 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 132 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 133 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 134 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 135 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 136 | 137 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 138 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 139 | 140 | #ifdef __cplusplus 141 | } 142 | #endif 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /pcs/dllmain.c: -------------------------------------------------------------------------------- 1 | #include "pcs_defs.h" 2 | #include "pcs_mem.h" 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | // Windows Header Files: 5 | #include 6 | 7 | BOOL APIENTRY DllMain( HMODULE hModule, 8 | DWORD ul_reason_for_call, 9 | LPVOID lpReserved 10 | ) 11 | { 12 | switch (ul_reason_for_call) 13 | { 14 | case DLL_PROCESS_ATTACH: 15 | case DLL_THREAD_ATTACH: 16 | case DLL_THREAD_DETACH: 17 | case DLL_PROCESS_DETACH: 18 | break; 19 | } 20 | return TRUE; 21 | } 22 | -------------------------------------------------------------------------------- /pcs/openssl_aes.h: -------------------------------------------------------------------------------- 1 | /* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ 2 | /* ==================================================================== 3 | * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * 17 | * 3. All advertising materials mentioning features or use of this 18 | * software must display the following acknowledgment: 19 | * "This product includes software developed by the OpenSSL Project 20 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 | * 22 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 | * endorse or promote products derived from this software without 24 | * prior written permission. For written permission, please contact 25 | * openssl-core@openssl.org. 26 | * 27 | * 5. Products derived from this software may not be called "OpenSSL" 28 | * nor may "OpenSSL" appear in their names without prior written 29 | * permission of the OpenSSL Project. 30 | * 31 | * 6. Redistributions of any form whatsoever must retain the following 32 | * acknowledgment: 33 | * "This product includes software developed by the OpenSSL Project 34 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 | * 36 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 | * OF THE POSSIBILITY OF SUCH DAMAGE. 48 | * ==================================================================== 49 | * 50 | */ 51 | 52 | #ifndef HEADER_AES_H 53 | #define HEADER_AES_H 54 | 55 | //#include 56 | 57 | #ifdef OPENSSL_NO_AES 58 | #error AES is disabled. 59 | #endif 60 | 61 | #include 62 | 63 | #define AES_ENCRYPT 1 64 | #define AES_DECRYPT 0 65 | 66 | /* Because array size can't be a const in C, the following two are macros. 67 | Both sizes are in bytes. */ 68 | #define AES_MAXNR 14 69 | #define AES_BLOCK_SIZE 16 70 | 71 | #ifdef __cplusplus 72 | extern "C" { 73 | #endif 74 | 75 | /* This should be a hidden type, but EVP requires that the size be known */ 76 | struct aes_key_st { 77 | #ifdef AES_LONG 78 | unsigned long rd_key[4 * (AES_MAXNR + 1)]; 79 | #else 80 | unsigned int rd_key[4 * (AES_MAXNR + 1)]; 81 | #endif 82 | int rounds; 83 | }; 84 | typedef struct aes_key_st AES_KEY; 85 | 86 | const char *AES_options(void); 87 | 88 | int AES_set_encrypt_key(const unsigned char *userKey, const int bits, 89 | AES_KEY *key); 90 | int AES_set_decrypt_key(const unsigned char *userKey, const int bits, 91 | AES_KEY *key); 92 | 93 | int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, 94 | AES_KEY *key); 95 | int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, 96 | AES_KEY *key); 97 | 98 | void AES_encrypt(const unsigned char *in, unsigned char *out, 99 | const AES_KEY *key); 100 | void AES_decrypt(const unsigned char *in, unsigned char *out, 101 | const AES_KEY *key); 102 | 103 | void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, 104 | const AES_KEY *key, const int enc); 105 | void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, 106 | size_t length, const AES_KEY *key, 107 | unsigned char *ivec, const int enc); 108 | void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, 109 | size_t length, const AES_KEY *key, 110 | unsigned char *ivec, int *num, const int enc); 111 | void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, 112 | size_t length, const AES_KEY *key, 113 | unsigned char *ivec, int *num, const int enc); 114 | void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, 115 | size_t length, const AES_KEY *key, 116 | unsigned char *ivec, int *num, const int enc); 117 | void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, 118 | size_t length, const AES_KEY *key, 119 | unsigned char *ivec, int *num); 120 | void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, 121 | size_t length, const AES_KEY *key, 122 | unsigned char ivec[AES_BLOCK_SIZE], 123 | unsigned char ecount_buf[AES_BLOCK_SIZE], 124 | unsigned int *num); 125 | /* NB: the IV is _two_ blocks long */ 126 | void AES_ige_encrypt(const unsigned char *in, unsigned char *out, 127 | size_t length, const AES_KEY *key, 128 | unsigned char *ivec, const int enc); 129 | /* NB: the IV is _four_ blocks long */ 130 | void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, 131 | size_t length, const AES_KEY *key, 132 | const AES_KEY *key2, const unsigned char *ivec, 133 | const int enc); 134 | 135 | int AES_wrap_key(AES_KEY *key, const unsigned char *iv, 136 | unsigned char *out, 137 | const unsigned char *in, unsigned int inlen); 138 | int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, 139 | unsigned char *out, 140 | const unsigned char *in, unsigned int inlen); 141 | 142 | 143 | #ifdef __cplusplus 144 | } 145 | #endif 146 | 147 | #endif /* !HEADER_AES_H */ 148 | -------------------------------------------------------------------------------- /pcs/openssl_md5.h: -------------------------------------------------------------------------------- 1 | #ifndef _OPENSSL_MD5_H 2 | #define _OPENSSL_MD5_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #ifdef OPENSSL_NO_MD5 11 | #error MD5 is disabled. 12 | #endif 13 | 14 | /* 15 | * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 16 | * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then ! 17 | * ! MD5_LONG_LOG2 has to be defined along. ! 18 | * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 19 | */ 20 | 21 | #if defined(__LP32__) 22 | #define MD5_LONG unsigned long 23 | #elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) 24 | #define MD5_LONG unsigned long 25 | #define MD5_LONG_LOG2 3 26 | /* 27 | * _CRAY note. I could declare short, but I have no idea what impact 28 | * does it have on performance on none-T3E machines. I could declare 29 | * int, but at least on C90 sizeof(int) can be chosen at compile time. 30 | * So I've chosen long... 31 | * 32 | */ 33 | #else 34 | #define MD5_LONG unsigned int 35 | #endif 36 | 37 | #define MD5_CBLOCK 64 38 | #define MD5_LBLOCK (MD5_CBLOCK/4) 39 | #define MD5_DIGEST_LENGTH 16 40 | 41 | typedef struct MD5state_st 42 | { 43 | MD5_LONG A, B, C, D; 44 | MD5_LONG Nl, Nh; 45 | MD5_LONG data[MD5_LBLOCK]; 46 | unsigned int num; 47 | } MD5_CTX; 48 | 49 | #ifdef OPENSSL_FIPS 50 | int private_MD5_Init(MD5_CTX *c); 51 | #endif 52 | int MD5_Init(MD5_CTX *c); 53 | int MD5_Update(MD5_CTX *c, const void *data, size_t len); 54 | int MD5_Final(unsigned char *md, MD5_CTX *c); 55 | unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md); 56 | void MD5_Transform(MD5_CTX *c, const unsigned char *b); 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /pcs/openssl_rsa.h: -------------------------------------------------------------------------------- 1 | #ifndef _OPENSSL_RSA_H 2 | #define _OPENSSL_RSA_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #ifdef OPENSSL_NO_RSA 11 | #error RSA is disabled. 12 | #endif 13 | 14 | typedef struct bio_st BIO; 15 | 16 | typedef struct rsa_st RSA; 17 | 18 | #define RSA_NO_PADDING 3 19 | 20 | BIO *BIO_new_mem_buf(void *buf, int len); 21 | 22 | typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata); 23 | 24 | RSA *PEM_read_bio_RSA_PUBKEY(BIO *bp, RSA **x, pem_password_cb *cb, void *u); 25 | 26 | RSA *PEM_read_bio_RSAPublicKey(BIO *bp, RSA **x, pem_password_cb *cb, void *u); 27 | int RSA_public_encrypt(int flen, const unsigned char *from, 28 | unsigned char *to, RSA *rsa,int padding); 29 | void RSA_free(RSA *r); 30 | 31 | void ERR_print_errors_fp(FILE *fp); 32 | 33 | 34 | 35 | typedef struct evp_Encode_Ctx_st 36 | { 37 | int num; /* number saved in a partial encode/decode */ 38 | int length; /* The length is either the output line length 39 | * (in input bytes) or the shortest input line 40 | * length that is ok. Once decoding begins, 41 | * the length is adjusted up each time a longer 42 | * line is decoded */ 43 | unsigned char enc_data[80]; /* data to encode */ 44 | int line_num; /* number read on current line */ 45 | int expect_nl; 46 | } EVP_ENCODE_CTX; 47 | 48 | void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); 49 | void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl, 50 | const unsigned char *in,int inl); 51 | void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /pcs/pcs_buffer.c: -------------------------------------------------------------------------------- 1 | #include "pcs_defs.h" 2 | #include "pcs_buffer.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "pcs_mem.h" 8 | 9 | int pcs_buf_init(pcs_buf_t *buf) 10 | { 11 | memset(buf, 0, sizeof(pcs_buf_t)); 12 | return 0; 13 | } 14 | 15 | void pcs_buf_free(pcs_buf_t *buf) 16 | { 17 | if (buf) { 18 | pcs_free(buf->data); 19 | } 20 | } 21 | 22 | int pcs_buf_enlarge(pcs_buf_t *buf, int want_size) 23 | { 24 | char *newdata; 25 | int sz = buf->len + want_size; 26 | if (sz <= buf->size) return 0; 27 | sz = buf->len + want_size * 2; 28 | if (sz != buf->size) { 29 | newdata = (char *)pcs_malloc(sz); 30 | if (!newdata) 31 | return -1; 32 | if (buf->data) { 33 | memcpy(newdata, buf->data, buf->len + 1); 34 | pcs_free(buf->data); 35 | } 36 | buf->data = newdata; 37 | buf->size = sz; 38 | } 39 | return 0; 40 | } 41 | 42 | int pcs_buf_write(pcs_buf_t *buf, const char *data, int size) 43 | { 44 | if (!data || size == 0) 45 | return 0; 46 | if (pcs_buf_enlarge(buf, size + 1)) 47 | return -1; 48 | memcpy(buf->data + buf->len, data, size); 49 | buf->len += size; 50 | buf->data[buf->len] = '\0'; 51 | return 0; 52 | } 53 | 54 | int pcs_buf_insert(pcs_buf_t *buf, int offset, const char *data, int size) 55 | { 56 | if (!data || size == 0) 57 | return 0; 58 | if (buf->len > offset) { 59 | if (pcs_buf_enlarge(buf, size + 1)) 60 | return -1; 61 | memmove(buf->data + offset + size, buf->data + offset, buf->len - offset + 1); 62 | memcpy(buf->data + offset, data, size); 63 | buf->len += size; 64 | } 65 | else { 66 | if (pcs_buf_enlarge(buf, offset + size - buf->len + 1)) 67 | return -1; 68 | memcpy(buf->data + offset, data, size); 69 | buf->len = offset + size; 70 | buf->data[buf->len] = '\0'; 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /pcs/pcs_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PCS_BUFFER_H_ 2 | #define PCS_BUFFER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct pcs_buf_t pcs_buf_t; 9 | 10 | struct pcs_buf_t { 11 | char *data; 12 | int len; 13 | int size; 14 | }; 15 | 16 | #define PCS_BUF_INIT() { 0 } 17 | 18 | int pcs_buf_init(pcs_buf_t *buf); 19 | 20 | void pcs_buf_free(pcs_buf_t *buf); 21 | 22 | /* 扩容,使得 buf 有足够的空间来装入 want_size 大小的数据 */ 23 | int pcs_buf_enlarge(pcs_buf_t *buf, int want_size); 24 | 25 | int pcs_buf_write(pcs_buf_t *buf, const char *data, int size); 26 | 27 | int pcs_buf_insert(pcs_buf_t *buf, int offset, const char *data, int size); 28 | 29 | #define pcs_buf_clear(buf) ((buf)->len = 0) 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* PCS_BUFFER_H_ */ 36 | -------------------------------------------------------------------------------- /pcs/pcs_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_DEFS_H 2 | #define _PCS_DEFS_H 3 | 4 | #include 5 | #include 6 | 7 | #if defined(_MSC_VER) || defined(__BORLANDC__) 8 | typedef __int64 int64_t; 9 | typedef unsigned __int64 uint64_t; 10 | # ifndef PRId64 11 | # define PRId64 "lld" 12 | # endif 13 | # ifndef PRIu64 14 | # define PRIu64 "llu" 15 | # endif 16 | #else 17 | # ifndef PRId64 18 | # define PRId64 "lld" 19 | # endif 20 | # ifndef PRIu64 21 | # define PRIu64 "llu" 22 | # endif 23 | #endif 24 | 25 | #ifdef WIN32 26 | # ifdef __cplusplus 27 | # if defined(PCS_STATIC_LIB) 28 | # define PCS_API extern "C" _declspec(dllexport) 29 | # elif defined(PCS_IMPORT_LIB) 30 | # define PCS_API extern "C" __declspec(dllimport) 31 | # else 32 | # define PCS_API extern "C" 33 | # endif 34 | # define PCS_EXTERN_C extern "C" 35 | # define PCS_EXTERN_C_BEGIN extern "C" { 36 | # define PCS_EXTERN_C_END } 37 | # else /* ifdef __cplusplus */ 38 | # if defined(PCS_STATIC_LIB) 39 | # define PCS_API _declspec(dllexport) 40 | # elif defined(PCS_IMPORT_LIB) 41 | # define PCS_API __declspec(dllimport) 42 | # else 43 | # define PCS_API 44 | # endif 45 | # define PCS_EXTERN_C 46 | # define PCS_EXTERN_C_BEGIN 47 | # define PCS_EXTERN_C_END 48 | # define inline __inline 49 | # endif /* ifdef __cplusplus */ 50 | #else /* ifdef WIN32 */ 51 | # ifdef __cplusplus 52 | # if defined(PCS_STATIC_LIB) 53 | # define PCS_API extern "C" 54 | # elif defined(PCS_IMPORT_LIB) 55 | # define PCS_API extern "C" 56 | # else 57 | # define PCS_API extern "C" 58 | # endif 59 | # define PCS_EXTERN_C extern "C" 60 | # define PCS_EXTERN_C_BEGIN extern "C" { 61 | # define PCS_EXTERN_C_END } 62 | # else /* ifdef __cplusplus */ 63 | # if defined(PCS_STATIC_LIB) 64 | # define PCS_API 65 | # elif defined(PCS_IMPORT_LIB) 66 | # define PCS_API 67 | # else 68 | # define PCS_API 69 | # endif 70 | # define PCS_EXTERN_C 71 | # define PCS_EXTERN_C_BEGIN 72 | # define PCS_EXTERN_C_END 73 | # endif /* ifdef __cplusplus */ 74 | #endif /* ifdef WIN32 */ 75 | 76 | #if defined(WIN32) 77 | # if !defined(__cplusplus) 78 | # define inline __inline 79 | # endif 80 | #endif 81 | 82 | #ifndef NULL 83 | # define NULL ((void *)0) 84 | #endif 85 | 86 | #define ToString(x) #x 87 | #define Xstr(x) ToString(x) 88 | 89 | typedef unsigned char PcsBool; 90 | # define PcsTrue 1 91 | # define PcsFalse 0 92 | 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /pcs/pcs_fileinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "pcs_mem.h" 6 | #include "pcs_utils.h" 7 | #include "pcs_fileinfo.h" 8 | 9 | PCS_API PcsFileInfo *pcs_fileinfo_create() 10 | { 11 | PcsFileInfo *res = 0; 12 | res = (PcsFileInfo *)pcs_malloc(sizeof(PcsFileInfo)); 13 | if (res) 14 | memset(res, 0, sizeof(PcsFileInfo)); 15 | return res; 16 | } 17 | 18 | PCS_API void pcs_fileinfo_destroy(PcsFileInfo *fi) 19 | { 20 | if (fi->path) pcs_free(fi->path); 21 | if (fi->server_filename) pcs_free(fi->server_filename); 22 | if (fi->md5) pcs_free(fi->md5); 23 | if (fi->dlink) pcs_free(fi->dlink); 24 | if (fi->block_list) { 25 | char **p = fi->block_list; 26 | while(*p) { 27 | pcs_free(*p); 28 | p++; 29 | } 30 | pcs_free(fi->block_list); 31 | } 32 | if (fi->thumbs) { 33 | pcs_slist2_destroy(fi->thumbs); 34 | } 35 | pcs_free(fi); 36 | } 37 | 38 | PCS_API PcsSList2 *pcs_fileinfo_add_thumb(PcsFileInfo *fi, const char *name, const char *url) 39 | { 40 | PcsSList2 *n; 41 | if (fi->thumbs) { 42 | n = pcs_slist2_add_ex(fi->thumbs, name, strlen(name), url, strlen(url)); 43 | } 44 | else { 45 | n = fi->thumbs = pcs_slist2_create_ex(name, strlen(name), url, strlen(url)); 46 | } 47 | return n; 48 | } 49 | 50 | PCS_API PcsFileInfo *pcs_fileinfo_clone(PcsFileInfo *fi) 51 | { 52 | PcsFileInfo *res = pcs_fileinfo_create(); 53 | if (!res) return 0; 54 | res->fs_id = fi->fs_id; 55 | res->path = pcs_utils_strdup(fi->path); 56 | res->server_filename = pcs_utils_strdup(fi->server_filename); 57 | res->server_ctime = fi->server_ctime; 58 | res->server_mtime = fi->server_mtime; 59 | res->local_ctime = fi->local_ctime; 60 | res->local_mtime = fi->local_mtime; 61 | res->size = fi->size; 62 | res->category = fi->category; 63 | res->isdir = fi->isdir; 64 | res->dir_empty = fi->dir_empty; 65 | res->empty = fi->empty; 66 | res->md5 = pcs_utils_strdup(fi->md5); 67 | res->dlink = pcs_utils_strdup(fi->dlink); 68 | if (fi->block_list) { 69 | char **p = fi->block_list; 70 | int i = 0; 71 | while(*p) { 72 | i++; 73 | p++; 74 | } 75 | res->block_list = (char **)pcs_malloc((i + 1) * sizeof(char *)); 76 | if (res->block_list) { 77 | i = 0; 78 | p = fi->block_list; 79 | while(*p) { 80 | res->block_list[i++] = pcs_utils_strdup(*p); 81 | p++; 82 | } 83 | } 84 | } 85 | res->ifhassubdir = fi->ifhassubdir; 86 | if (fi->thumbs) { 87 | res->thumbs = pcs_slist2_clone(fi->thumbs); 88 | } 89 | return res; 90 | } 91 | 92 | 93 | PCS_API PcsFileInfoListItem *pcs_filistitem_create() 94 | { 95 | PcsFileInfoListItem *res = 0; 96 | res = (PcsFileInfoListItem *)pcs_malloc(sizeof(PcsFileInfoListItem)); 97 | if (res) 98 | memset(res, 0, sizeof(PcsFileInfoListItem)); 99 | return res; 100 | } 101 | 102 | PCS_API void pcs_filistitem_destroy(PcsFileInfoListItem *item) 103 | { 104 | if (item->info) pcs_fileinfo_destroy(item->info); 105 | pcs_free(item); 106 | } 107 | 108 | 109 | PCS_API PcsFileInfoList *pcs_filist_create() 110 | { 111 | PcsFileInfoList *res = 0; 112 | res = (PcsFileInfoList *)pcs_malloc(sizeof(PcsFileInfoList)); 113 | if (res) 114 | memset(res, 0, sizeof(PcsFileInfoList)); 115 | return res; 116 | } 117 | 118 | PCS_API void pcs_filist_destroy(PcsFileInfoList *list) 119 | { 120 | PcsFileInfoListItem *p = list->link, *p2; 121 | while(p) { 122 | p2 = p; 123 | p = p->next; 124 | pcs_filistitem_destroy(p2); 125 | } 126 | pcs_free(list); 127 | } 128 | 129 | PCS_API void pcs_filist_add(PcsFileInfoList *list, PcsFileInfoListItem *item) 130 | { 131 | if (!list->link_tail) { 132 | list->link = list->link_tail = item; 133 | item->prev = item->next = 0; 134 | } 135 | else { 136 | item->prev = list->link_tail; 137 | item->next = 0; 138 | list->link_tail->next = item; 139 | list->link_tail = item; 140 | } 141 | list->count++; 142 | } 143 | 144 | PCS_API void pcs_filist_remove(PcsFileInfoList *list, PcsFileInfoListItem *item, PcsFileInfoListIterater *iterater) 145 | { 146 | if (item->prev) 147 | item->prev->next = item->next; 148 | if (item->next) 149 | item->next->prev = item->prev; 150 | if (list->link == item) 151 | list->link = item->next; 152 | if (list->link_tail == item) 153 | list->link_tail = item->prev; 154 | if (iterater && iterater->cursor == item) { 155 | if (iterater->invert) 156 | iterater->cursor = item->next; 157 | else 158 | iterater->cursor = item->prev; 159 | } 160 | item->prev = item->next = 0; 161 | list->count--; 162 | } 163 | 164 | PCS_API void pcs_filist_combin(PcsFileInfoList *list, PcsFileInfoList *src) 165 | { 166 | if (!src->link) 167 | return; 168 | if (!list->link_tail) { 169 | list->link = src->link; 170 | list->link_tail = src->link_tail; 171 | list->count = src->count; 172 | src->count = 0; 173 | src->link = src->link_tail = 0; 174 | } 175 | else { 176 | list->link_tail->next = src->link; 177 | src->link->prev = list->link_tail; 178 | list->link_tail = src->link_tail; 179 | list->count += src->count; 180 | src->count = 0; 181 | src->link = src->link_tail = 0; 182 | } 183 | } 184 | 185 | 186 | PCS_API void pcs_filist_iterater_init(PcsFileInfoList *list, PcsFileInfoListIterater *iterater, PcsBool invert) 187 | { 188 | memset(iterater, 0, sizeof(PcsFileInfoListIterater)); 189 | iterater->invert = invert; 190 | iterater->list = list; 191 | } 192 | 193 | PCS_API PcsBool pcs_filist_iterater_next(PcsFileInfoListIterater *iterater) 194 | { 195 | if (!iterater->list->link) 196 | return PcsFalse; 197 | if (iterater->invert) { 198 | if (!iterater->cursor) { 199 | iterater->cursor = iterater->list->link_tail; 200 | iterater->current = iterater->cursor->info; 201 | return PcsTrue; 202 | } 203 | else if (iterater->cursor->prev) { 204 | iterater->cursor = iterater->cursor->prev; 205 | iterater->current = iterater->cursor->info; 206 | return PcsTrue; 207 | } 208 | } 209 | else { 210 | if (!iterater->cursor) { 211 | iterater->cursor = iterater->list->link; 212 | iterater->current = iterater->cursor->info; 213 | return PcsTrue; 214 | } 215 | else if (iterater->cursor->next) { 216 | iterater->cursor = iterater->cursor->next; 217 | iterater->current = iterater->cursor->info; 218 | return PcsTrue; 219 | } 220 | } 221 | return PcsFalse; 222 | } 223 | 224 | -------------------------------------------------------------------------------- /pcs/pcs_fileinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_FILEINFO_H 2 | #define _PCS_FILEINFO_H 3 | 4 | #include "pcs_defs.h" 5 | #include "pcs_slist.h" 6 | 7 | /* 用于存储网盘中文件的元数据 */ 8 | typedef struct PcsFileInfo { 9 | uint64_t fs_id; 10 | char *path; 11 | char *server_filename; 12 | time_t server_ctime; 13 | time_t server_mtime; 14 | time_t local_ctime; 15 | time_t local_mtime; 16 | int64_t size; 17 | int category; 18 | PcsBool isdir; 19 | PcsBool dir_empty; 20 | PcsBool empty; 21 | char *md5; 22 | char *dlink; 23 | char **block_list; /* 文件所有分片的md5数组json字符串, 只有 pcs_meta() 设置该值 */ 24 | PcsBool ifhassubdir; /* 是否含有子目录, 只有 pcs_meta() 设置该值 */ 25 | 26 | int user_flag; 27 | 28 | PcsSList2 *thumbs; 29 | } PcsFileInfo; 30 | 31 | /*网盘中文件元数据链表的单个节点*/ 32 | typedef struct PcsFileInfoListItem { 33 | PcsFileInfo *info; 34 | struct PcsFileInfoListItem *prev; 35 | struct PcsFileInfoListItem *next; 36 | } PcsFileInfoListItem; 37 | 38 | /*以链表形式存储的网盘文件元数据列表*/ 39 | typedef struct PcsFileInfoList { 40 | int count; 41 | PcsFileInfoListItem *link; 42 | PcsFileInfoListItem *link_tail; 43 | } PcsFileInfoList; 44 | 45 | /*网盘文件元数据列表的迭代器*/ 46 | typedef struct PcsFileInfoListIterater { 47 | PcsBool invert; 48 | PcsFileInfoList *list; 49 | PcsFileInfoListItem *cursor; 50 | PcsFileInfo *current; 51 | } PcsFileInfoListIterater; 52 | 53 | PCS_API PcsFileInfo *pcs_fileinfo_create(); 54 | PCS_API void pcs_fileinfo_destroy(PcsFileInfo *fi); 55 | /*复制一份PcsFileInfo。注意是深克隆。*/ 56 | PCS_API PcsFileInfo *pcs_fileinfo_clone(PcsFileInfo *fi); 57 | /*添加缩略图到 fi 中*/ 58 | PCS_API PcsSList2 *pcs_fileinfo_add_thumb(PcsFileInfo *fi, const char *name, const char *url); 59 | 60 | PCS_API PcsFileInfoListItem *pcs_filistitem_create(); 61 | PCS_API void pcs_filistitem_destroy(PcsFileInfoListItem *item); 62 | 63 | PCS_API PcsFileInfoList *pcs_filist_create(); 64 | PCS_API void pcs_filist_destroy(PcsFileInfoList *list); 65 | PCS_API void pcs_filist_add(PcsFileInfoList *list, PcsFileInfoListItem *item); 66 | PCS_API void pcs_filist_remove(PcsFileInfoList *list, PcsFileInfoListItem *item, PcsFileInfoListIterater *iterater); 67 | PCS_API void pcs_filist_combin(PcsFileInfoList *list, PcsFileInfoList *src); 68 | 69 | /* 70 | * invert - 是否从后向前迭代 71 | */ 72 | PCS_API void pcs_filist_iterater_init(PcsFileInfoList *list, PcsFileInfoListIterater *iterater, PcsBool invert); 73 | PCS_API PcsBool pcs_filist_iterater_next(PcsFileInfoListIterater *iterater); 74 | 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /pcs/pcs_http.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_HTTP_H 2 | #define _PCS_HTTP_H 3 | 4 | #include 5 | #include "pcs_defs.h" 6 | 7 | typedef void *PcsHttp; 8 | typedef void *PcsHttpForm; 9 | 10 | /* 11 | * 设定该回调后,Pcs每从网络获取到值,则调用该回调。例如下载时。 12 | * ptr 从网络获取到的字节序 13 | * size 字节序的大小,以字节为单位 14 | * contentlength 本次请求,HTTP头中的Content-Length值 15 | * userdata 使用PCS_OPTION_DOWNLOAD_WRITE_FUNCTION_DATA选项设定的值原样传入 16 | * 返回写入的字节数,如果返回值和传入的size不一样,将导致下载中断 17 | */ 18 | typedef size_t (*PcsHttpWriteFunction)(char *ptr, size_t size, size_t contentlength, void *userdata); 19 | 20 | /* 21 | * 设定该回调后,Pcs每从网络获取到值,则调用该回调。 22 | * 和PcsHttpWriteFunction的区别是,该回调是在获取到全部内容后触发, 23 | * 而PcsHttpWriteFunction是每获取到一段字节序则触发。 24 | * 每个HTTP请求,PcsHttpResponseFunction只会触发一次,而PcsHttpWriteFunction可能触发多次 25 | * ptr 从网络获取到的字节序 26 | * size 字节序的大小,以字节为单位 27 | * userdata 使用PCS_OPTION_HTTP_RESPONSE_FUNCTION_DATE选项设定的值原样传入 28 | */ 29 | typedef void (*PcsHttpResponseFunction)(unsigned char *ptr, size_t size, void *state); 30 | 31 | /* 32 | * 设定该回调后,Pcs每上传或下载一段字节序到网络中时,则调用该回调。利用该回调可实现上传时的进度条 33 | * 注意:只有设定PCS_OPTION_PROGRESS的值为PcsTrue后才会启用进度条 34 | * dltotal 从网络中需要下载多少字节 35 | * dlnow 从网络中已经下载多少字节 36 | * ultotal 需要上传多少字节 37 | * ulnow 已经上传多少字节 38 | * clientp 使用PCS_OPTION_PROGRESS_FUNCTION_DATE选项设定的值原样传入 39 | * 返回非零值,将导致中断上传或下载 40 | */ 41 | typedef int (*PcsHttpProgressCallback)(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); 42 | 43 | typedef enum PcsHttpOption { 44 | PCS_HTTP_OPTION_END = 0, 45 | /* 值为PcsHttpWriteFunction类型的函数。当调用pcs_http_get_download方法时,此选项传入的函数用于处理服务器返回的数据。 */ 46 | PCS_HTTP_OPTION_HTTP_WRITE_FUNCTION, 47 | /* PcsHttp本身不使用该值,仅原样传递到PcsHttpWriteFunction函数中。 48 | 当调用pcs_http_get_download方法时,此选项传入的对象原样传递到PcsHttpWriteFunction指定的函数中。 */ 49 | PCS_HTTP_OPTION_HTTP_WRITE_FUNCTION_DATE, 50 | /* 值为PcsHttpReadFunction类型的函数。保留,未使用。 */ 51 | PCS_HTTP_OPTION_HTTP_READ_FUNCTION, 52 | /* PcsHttp本身不使用该值,仅原样传递到PcsHttpReadFunction函数中。保留,未使用。 */ 53 | PCS_HTTP_OPTION_HTTP_READ_FUNCTION_DATE, 54 | /* 值为PcsHttpResponseFunction类型的函数 */ 55 | PCS_HTTP_OPTION_HTTP_RESPONSE_FUNCTION, 56 | /* PcsHttp本身不使用该值,仅原样传递到PcsHttpResponseFunction函数中 */ 57 | PCS_HTTP_OPTION_HTTP_RESPONSE_FUNCTION_DATE, 58 | /* 值为PcsHttpProgressCallback类型的函数 */ 59 | PCS_HTTP_OPTION_PROGRESS_FUNCTION, 60 | /* PcsHttp本身不使用该值,仅原样传递到PcsHttpProgressCallback函数中 */ 61 | PCS_HTTP_OPTION_PROGRESS_FUNCTION_DATE, 62 | /* 设置是否启用下载或上传进度,值为unsigned char类型指针 */ 63 | PCS_HTTP_OPTION_PROGRESS, 64 | /* 设置USAGE,值为char类型指针 */ 65 | PCS_HTTP_OPTION_USAGE, 66 | /*设置整个请求的超时时间,值为long类型*/ 67 | PCS_HTTP_OPTION_TIMEOUT, 68 | /*设置连接前的等待时间,值为long类型*/ 69 | PCS_HTTP_OPTION_CONNECTTIMEOUT, 70 | 71 | 72 | } PcsHttpOption; 73 | 74 | /* 75 | * 创建一个PcsHttp对象 76 | * cookie_file 指定保存Cookie的文件,如果文件不存在,将自动创建该文件。 77 | * 当发送一个请求时,将附加该文件中的Cookie。程序退出后,保存最新的Cookie到该文件中。 78 | * 成功后,返回创建的对象,失败则返回NULL。使用完成后需调用pcs_http_destroy()来释放资源 79 | */ 80 | PCS_API PcsHttp pcs_http_create(const char *cookie_file); 81 | /* 82 | * 释放掉PcsHttp对象 83 | */ 84 | PCS_API void pcs_http_destroy(PcsHttp handle); 85 | /* 86 | * 返回最后一次发生的错误描述 87 | */ 88 | PCS_API const char *pcs_http_strerror(PcsHttp handle); 89 | /* 90 | * 返回最后一次请求的 HTTP状态码。状态码可参考"http://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81" 91 | */ 92 | PCS_API int pcs_http_code(PcsHttp handle); 93 | /* 94 | * 设置PcsHttp配置选项,每次只能设置一个。 95 | */ 96 | PCS_API void pcs_http_setopt(PcsHttp handle, PcsHttpOption opt, void *value); 97 | 98 | /* 99 | * 一次设定多个配置选项,最后一项必须为PCS_HTTP_OPTION_END。 100 | * 例: pcs_http_setopts(handle, PCS_HTTP_OPTION_HTTP_WRITE_FUNCTION, &cb_write, PCS_HTTP_OPTION_HTTP_READ_FUNCTION_DATE, state, PCS_HTTP_OPTION_END); 101 | */ 102 | PCS_API void pcs_http_setopts(PcsHttp handle, ...); 103 | /* 104 | * pcs_http_build_url的参数列表模式 105 | * Need call pcs_free(void *) to free the return value. 106 | */ 107 | PCS_API char *pcs_http_build_url_v(PcsHttp handle, const char *url, va_list args); 108 | /* 109 | * 拼接URL。多参必须全部为 Key-Value的键值对,且类型必须const char *类型。最后一项必须为NULL。 110 | * 如果值中包含中文或特殊字符,将采用UTF-8来编码。 111 | * url - 基地址 112 | * 例: 113 | * pcs_http_build_url(pcs->http, "http://baidu.com", "key1", "value1", "key2", "value2", NULL); //结果为:http://baidu.com?key1=value1&key2=value2 114 | * pcs_http_build_url(pcs->http, "http://baidu.com?s=ab", "key1", "value1", "key2", "&ab", NULL); //结果为:http://baidu.com??s=ab&key1=value1&key2=%26ab 115 | * pcs_http_build_url(pcs->http, "http://baidu.com?s=ab&", "key1", "value1", "key2", "&ab", NULL); //结果为:http://baidu.com??s=ab&key1=value1&key2=%26ab 116 | * 成功后返回拼接后的地址,失败则返回NULL 117 | * Need call pcs_free(void *) to free the return value. 118 | */ 119 | PCS_API char *pcs_http_build_url(PcsHttp handle, const char *url, ...); 120 | /* 121 | * pcs_http_build_post_data的参数列表模式 122 | * Need call pcs_free(void *) to free the return value. 123 | */ 124 | PCS_API char *pcs_http_build_post_data_v(PcsHttp handle, va_list args); 125 | /* 126 | * 类似于pcs_http_build_url,只不过该函数拼接的是需要发送到服务的数据。 127 | * 多参必须全部为 Key-Value的键值对,且类型必须const char *类型。最后一项必须为NULL。 128 | * 如果值中包含中文或特殊字符,将采用UTF-8来编码。 129 | * url - 基地址 130 | * 例: 131 | * pcs_http_build_post_data(pcs->http, "key1", "value1", "key2", "value2", NULL); //结果为:key1=value1&key2=value2 132 | * pcs_http_build_post_data(pcs->http, "key1", "value1", "key2", "&ab", NULL); //结果为:key1=value1&key2=%26ab 133 | * 成功后返回拼接后的字符串,失败则返回NULL 134 | * Need call pcs_free(void *) to free the return value. 135 | */ 136 | PCS_API char *pcs_http_build_post_data(PcsHttp handle, ...); 137 | /* 138 | * 根据名字获取Cookie值。 139 | * 成功后返回Cookie值,失败或不存在则返回NULL。 140 | * Need call pcs_free(void *) to free the return value. 141 | */ 142 | PCS_API char *pcs_http_get_cookie(PcsHttp handle, const char *cookie_name); 143 | 144 | /* 145 | * 获取最后一次请求时服务器的返回内容 146 | * 如果从未从服务器请求数据则返回NULL。不需要调用pcs_free释放内存。 147 | */ 148 | PCS_API const char *pcs_http_get_response(PcsHttp handle); 149 | /* 150 | * 获取最后一次请求时服务器返回内容的字节长度 151 | * 如果从未从服务器请求数据则返回0。 152 | */ 153 | PCS_API int pcs_http_get_response_size(PcsHttp handle); 154 | /* 155 | * 向服务器发送一个GET请求。 156 | * url 服务器地址 157 | * follow_location 假如服务器返回跳转到另一个页面的指令时,是否自动跳转过去,如果跳转的话,则返回跳转后页面的内容 158 | * 返回服务器返回的内容。内容自动解码为当前操作系统使用的编码。 159 | * 例如:在Windows系统中,如果系统编码为GB2312,则返回内容自动解码为GB2312编码;在Linux系统中,系统编码为UTF-8,则返回内容的编码则为UTF-8 160 | * Not need call pcs_free(void *) to free the return value. 161 | * The memory will auto free when call pcs_http_destroy 162 | */ 163 | PCS_API char *pcs_http_get(PcsHttp handle, const char *url, PcsBool follow_location); 164 | /* 165 | * 向服务器发送一个GET请求。 166 | * url 服务器地址 167 | * follow_location 假如服务器返回跳转到另一个页面的指令时,是否自动跳转过去,如果跳转的话,则返回跳转后页面的内容 168 | * 返回服务器返回的内容。内容不会执行解码操作。该方法一般用于获取图片或用于获取服务中文件的原始内容。 169 | * Not need call pcs_free(void *) to free the return value. 170 | * The memory will auto free when call pcs_http_destroy 171 | */ 172 | PCS_API char *pcs_http_get_raw(PcsHttp handle, const char *url, PcsBool follow_location, size_t *sz); 173 | /* 174 | * 向服务器发送一个POST请求。 175 | * url 服务器地址 176 | * follow_location 假如服务器返回跳转到另一个页面的指令时,是否自动跳转过去,如果跳转的话,则返回跳转后页面的内容 177 | * 返回服务器返回的内容。内容自动解码为当前操作系统使用的编码。 178 | * 例如:在Windows系统中,如果系统编码为GB2312,则返回内容自动解码为GB2312编码;在Linux系统中,系统编码为UTF-8,则返回内容的编码则为UTF-8 179 | * Not need call pcs_free(void *) to free the return value. 180 | * The memory will auto free when call pcs_http_destroy 181 | */ 182 | PCS_API char *pcs_http_post(PcsHttp handle, const char *url, char *post_data, PcsBool follow_location); 183 | 184 | /* 185 | * 向服务器发送一个GET请求。当获取到服务器返回数据后,调用PCS_HTTP_OPTION_HTTP_WRITE_FUNCTION传入的函数来写入内容。 186 | * url 服务器地址 187 | * follow_location 假如服务器返回跳转到另一个页面的指令时,是否自动跳转过去,如果跳转的话,则返回跳转后页面的内容 188 | * 返回是否下载成功。内容不会执行解码操作。该方法一般用于下载图片或文件。 189 | * Not need call pcs_free(void *) to free the return value. 190 | * The memory will auto free when call pcs_http_destroy 191 | */ 192 | PCS_API PcsBool pcs_http_get_download(PcsHttp handle, const char *url, PcsBool follow_location, curl_off_t max_speed, curl_off_t resume_from, curl_off_t max_length); 193 | 194 | /*获取待下载文件的大小*/ 195 | PCS_API int64_t pcs_http_get_download_filesize(PcsHttp handle, const char *url, PcsBool follow_location); 196 | 197 | /* 198 | * 向PcsHttpForm对象中添加一个本地文件。 199 | * post 文件将添加到该PcsHttpForm对象中。 200 | * param_name 发送给服务器的代表该文件内容的参数名字。 201 | * filename 该文件的本地文件名,PcsHttpForm将从该路径读取文件内容 202 | * simulate_filename 发送到服务器的文件名。可以指定不同于filename的名字,服务器收到的本地文件名将是simulate_filename而不是filename 203 | * 例: pcs_http_form_addfile(pcs->http, &form, "file", local_filename, "sample.dat"); //参数名是 "file",文件内容存储在local_filename指定的文件中,服务器接收到的文件名字是"sample.dat" 204 | * 添加成功后,返回PcsTrue,否则返回PcsFalse。 205 | */ 206 | PCS_API PcsBool pcs_http_form_addfile(PcsHttp handle, PcsHttpForm *post, const char *param_name, 207 | const char *filename, const char *simulate_filename); 208 | /* 209 | * 向PcsHttpForm对象中添加一个内存文件。程序将调用 210 | * post 文件将添加到该PcsHttpForm对象中。 211 | * param_name 发送给服务器的代表该文件内容的参数名字。 212 | * simulate_filename 发送到服务器的文件名。可以指定不同于filename的名字,服务器收到的本地文件名将是simulate_filename而不是filename 213 | * read_func 用于读取内存文件的函数。 214 | * The data area pointed at by the pointer ptr may be filled with at most size multiplied with nmemb number of bytes. 215 | * Your function must return the actual number of bytes that you stored in that memory area. Returning 0 will signal 216 | * end-of-file to the library and cause it to stop the current transfer. 217 | * userdata 传递到read_func函数第4个参数的值 218 | * content_size 期望传递到服务器的内容长度。将会添加到HTTP头中。 219 | * 添加成功后,返回PcsTrue,否则返回PcsFalse。 220 | */ 221 | PCS_API PcsBool pcs_http_form_addbufferfile(PcsHttp handle, PcsHttpForm *post, const char *param_name, const char *simulate_filename, 222 | size_t(*read_func)(void *ptr, size_t size, size_t nmemb, void *userdata), void *userdata, size_t content_size); 223 | 224 | /* 同pcs_http_form_addfile,只不过是从内存中读取文件内容。 */ 225 | PCS_API PcsBool pcs_http_form_addbuffer(PcsHttp handle, PcsHttpForm *post, const char *param_name, 226 | const char *buffer, long buffer_size, const char *simulate_filename); 227 | /*释放掉PcsHttpForm资源*/ 228 | PCS_API void pcs_http_form_destroy(PcsHttp handle, PcsHttpForm post); 229 | 230 | /* 231 | * 向服务器发送一个POST请求。该方法可以上传文件到服务器。 232 | * url 服务器地址 233 | * data 发送到服务器的数据。 234 | * max_speed 最大上传速度。 235 | * follow_location 假如服务器返回跳转到另一个页面的指令时,是否自动跳转过去,如果跳转的话,则返回跳转后页面的内容 236 | * 返回服务器返回的内容。内容自动解码为当前操作系统使用的编码。 237 | * 例如:在Windows系统中,如果系统编码为GB2312,则返回内容自动解码为GB2312编码;在Linux系统中,系统编码为UTF-8,则返回内容的编码则为UTF-8 238 | * Not need call pcs_free(void *) to free the return value. 239 | * The memory will auto free when call pcs_http_destroy 240 | */ 241 | PCS_API char *pcs_post_httpform(PcsHttp handle, const char *url, PcsHttpForm data, curl_off_t max_speed, PcsBool follow_location); 242 | 243 | /*以字符串形式返回所有Cookie数据。*/ 244 | PCS_API char *pcs_http_cookie_data(PcsHttp handle); 245 | 246 | /*返回最后一次请求的服务器回应内容。 247 | * size - 用于接收服务器返回值的字节大小 248 | * encode - 用于接收服务器返回值的编码 249 | *返回缓存中的服务器返回内容。 250 | */ 251 | PCS_API const char *pcs_http_rawdata(PcsHttp handle, int *size, const char **encode); 252 | 253 | /*返回下载速度。通过curl_easy_getinfo(http->curl, CURLINFO_SPEED_DOWNLOAD, &downloadSpeed)来获取。*/ 254 | PCS_API double pcs_http_speed_download(PcsHttp handle); 255 | 256 | /* 257 | * 解码s字符串,结果保存在s字符串中。 258 | * 返回 s 字符串指针。 259 | */ 260 | PCS_API char *pcs_http_url_decode(PcsHttp handle, char *s); 261 | 262 | /* 当 pcs_http_get() 设置为不跟随跳转时,可通过此方法获取目标地址。 263 | * 返回 30x 的目标地址。 264 | */ 265 | PCS_API const char *pcs_http_redir_url(PcsHttp handle); 266 | 267 | #endif 268 | -------------------------------------------------------------------------------- /pcs/pcs_mem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "pcs_defs.h" 5 | 6 | struct pcs_mem { 7 | struct pcs_mem *prev; 8 | struct pcs_mem *next; 9 | 10 | void *ptr; 11 | const char *filename; 12 | int line; 13 | 14 | }; 15 | 16 | typedef void(*pcs_mem_leak_print_fun)(void *ptr, const char *filename, int line); 17 | 18 | static void cb_leak_printf(void *ptr, const char *filename, int line); 19 | 20 | static struct pcs_mem *_mem = 0; 21 | static pcs_mem_leak_print_fun _print = cb_leak_printf; 22 | 23 | static void cb_leak_printf(void *ptr, const char *filename, int line) 24 | { 25 | printf("Memory leak on %p %s, %d\n", ptr, filename, line); 26 | } 27 | 28 | static inline void append_mem_ent(struct pcs_mem *mem) 29 | { 30 | if (!_mem) { 31 | _mem = mem; 32 | mem->next = mem; 33 | mem->prev = mem; 34 | } 35 | else { 36 | mem->next = _mem; 37 | mem->prev = _mem->prev; 38 | _mem->prev->next = mem; 39 | _mem->prev = mem; 40 | } 41 | } 42 | 43 | static inline void remove_mem_ent(struct pcs_mem *mem) 44 | { 45 | if (mem->next == mem) { 46 | _mem = 0; 47 | return; 48 | } 49 | else { 50 | if (mem == _mem) _mem = _mem->next; 51 | mem->prev->next = mem->next; 52 | mem->next->prev = mem->prev; 53 | } 54 | } 55 | 56 | PCS_API void *pcs_mem_malloc(size_t size, const char *filename, int line) 57 | { 58 | struct pcs_mem *ent; 59 | ent = (struct pcs_mem *) malloc(sizeof(struct pcs_mem) + size); 60 | ent->ptr = (void *)(((char *)ent) + sizeof(struct pcs_mem)); 61 | ent->filename = filename; 62 | ent->line = line; 63 | append_mem_ent(ent); 64 | return ent->ptr; 65 | } 66 | 67 | PCS_API void *pcs_mem_malloc_arg1(size_t sz) 68 | { 69 | return pcs_mem_malloc(sz, "unknow", 0); 70 | } 71 | 72 | PCS_API void pcs_mem_free(void *ptr) 73 | { 74 | if (!ptr) return; 75 | struct pcs_mem *ent; 76 | ent = (struct pcs_mem *)(((char *)ptr) - sizeof(struct pcs_mem)); 77 | remove_mem_ent(ent); 78 | free(ent); 79 | } 80 | 81 | PCS_API void pcs_mem_print_leak() 82 | { 83 | struct pcs_mem *ent, *p; 84 | if (!_mem) return; 85 | ent = _mem; 86 | do { 87 | _print(ent->ptr, ent->filename, ent->line); 88 | ent = ent->next; 89 | } while(ent != _mem); 90 | ent = _mem; 91 | do { 92 | p = ent; 93 | ent = ent->next; 94 | free(p); 95 | } while(ent != _mem); 96 | _mem = 0; 97 | } 98 | 99 | PCS_API void *pcs_mem_malloc_raw(size_t size) 100 | { 101 | return malloc(size); 102 | } 103 | 104 | PCS_API void pcs_mem_free_raw(void *ptr) 105 | { 106 | free(ptr); 107 | } 108 | 109 | PCS_API void pcs_mem_set_print_func(pcs_mem_leak_print_fun print) 110 | { 111 | _print = print; 112 | } 113 | 114 | -------------------------------------------------------------------------------- /pcs/pcs_mem.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_MEM_H 2 | #define _PCS_MEM_H 3 | 4 | /* 自定义malloc,free方法。用于检查内存泄漏。 */ 5 | #ifdef WIN32 6 | # include 7 | #else 8 | # include 9 | #endif 10 | #include "pcs_defs.h" 11 | 12 | typedef void(*pcs_mem_leak_print_fun)(void *ptr, const char *filename, int line); 13 | 14 | /* 原始的 malloc() 函数 */ 15 | PCS_API void *pcs_mem_malloc_raw(size_t size); 16 | /* 原始的 free() 函数 */ 17 | PCS_API void pcs_mem_free_raw(void *ptr); 18 | 19 | /* 带有泄漏检测的 malloc() 函数 */ 20 | PCS_API void *pcs_mem_malloc(size_t size, const char *filename, int line); 21 | /* 带有泄漏检测的 malloc() 函数 */ 22 | PCS_API void *pcs_mem_malloc_arg1(size_t sz); 23 | /* 带有泄漏检测的 free() 函数 */ 24 | PCS_API void pcs_mem_free(void *p); 25 | /* 打印泄漏的内存 */ 26 | PCS_API void pcs_mem_print_leak(); 27 | 28 | PCS_API void pcs_mem_set_print_func(pcs_mem_leak_print_fun print); 29 | 30 | 31 | #if defined(DEBUG) || defined(_DEBUG) 32 | 33 | # define pcs_print_leak() pcs_mem_print_leak() 34 | # define pcs_malloc(size) pcs_mem_malloc(size, __FILE__, __LINE__) 35 | # define pcs_free(ptr) pcs_mem_free(ptr) 36 | 37 | #else 38 | # include 39 | # define pcs_print_leak() while(0) 40 | # define pcs_malloc(size) malloc(size) 41 | # define pcs_free(ptr) free(ptr) 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /pcs/pcs_pan_api_resinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #ifdef WIN32 3 | # include 4 | #else 5 | # include 6 | #endif 7 | 8 | #include "pcs_mem.h" 9 | #include "pcs_pan_api_resinfo.h" 10 | 11 | PCS_API const char *pcs_pan_api_res_info_errmsg(int error) 12 | { 13 | const char *errmsg = NULL; 14 | switch (error) { 15 | case 0: //处理成功 16 | errmsg = "成功"; 17 | break; 18 | case -8: //文件已存在于目标文件夹中 19 | errmsg = "文件已存在于目标文件夹中"; 20 | break; 21 | case -9: //文件不存在 22 | errmsg = "文件不存在"; 23 | break; 24 | case -10: //剩余空间不足 25 | errmsg = "剩余空间不足"; 26 | break; 27 | default: 28 | errmsg = "未知错误"; 29 | } 30 | return errmsg; 31 | } 32 | 33 | PCS_API PcsPanApiRes *pcs_pan_api_res_create() 34 | { 35 | PcsPanApiRes *res = (PcsPanApiRes *)pcs_malloc(sizeof(PcsPanApiRes)); 36 | if (res) 37 | memset(res, 0, sizeof(PcsPanApiRes)); 38 | return res; 39 | } 40 | 41 | PCS_API void pcs_pan_api_res_destroy(PcsPanApiRes *res) 42 | { 43 | if (res->info_list) 44 | pcs_pan_api_res_infolist_destroy(res->info_list); 45 | pcs_free(res); 46 | } 47 | 48 | PCS_API PcsPanApiResInfoList *pcs_pan_api_res_infolist_create() 49 | { 50 | PcsPanApiResInfoList *res = (PcsPanApiResInfoList *)pcs_malloc(sizeof(PcsPanApiResInfoList)); 51 | if (res) 52 | memset(res, 0, sizeof(PcsPanApiResInfoList)); 53 | return res; 54 | } 55 | 56 | PCS_API void pcs_pan_api_res_infolist_destroy(PcsPanApiResInfoList *infolist) 57 | { 58 | PcsPanApiResInfoList *p, *p2; 59 | p = infolist; 60 | while(p) { 61 | p2 = p; 62 | p = p->next; 63 | if (p2->info.path) 64 | pcs_free(p2->info.path); 65 | pcs_free(p2); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /pcs/pcs_pan_api_resinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_PAN_API_RESINFO_H 2 | #define _PCS_PAN_API_RESINFO_H 3 | 4 | /*网盘API返回数据格式*/ 5 | typedef struct PcsPanApiResInfo { 6 | char *path; 7 | int error; 8 | } PcsPanApiResInfo; 9 | 10 | typedef struct PcsPanApiResInfoList { 11 | PcsPanApiResInfo info; 12 | struct PcsPanApiResInfoList *next; 13 | } PcsPanApiResInfoList; 14 | 15 | typedef struct PcsPanApiRes { 16 | int error; 17 | PcsPanApiResInfoList *info_list; 18 | } PcsPanApiRes; 19 | 20 | PCS_API const char *pcs_pan_api_res_info_errmsg(int error); 21 | 22 | PCS_API PcsPanApiRes *pcs_pan_api_res_create(); 23 | PCS_API void pcs_pan_api_res_destroy(PcsPanApiRes *res); 24 | 25 | PCS_API PcsPanApiResInfoList *pcs_pan_api_res_infolist_create(); 26 | PCS_API void pcs_pan_api_res_infolist_destroy(PcsPanApiResInfoList *infolist); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /pcs/pcs_passport_dv.h: -------------------------------------------------------------------------------- 1 | #ifndef PCS_PASSPORT_DV_H_ 2 | #define PCS_PASSPORT_DV_H_ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /* 产生 dv 11 | * pdv - 用于接收产生的 dv,需要 free(*pdv) 12 | * starttime - 登录页面打开的时间 13 | */ 14 | int passport_build_dv(char **pdv, int64_t starttime, const char *username); 15 | 16 | int passport_print_dv(const char *dv); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif /* PCS_PASSPORT_DV_H_ */ 23 | -------------------------------------------------------------------------------- /pcs/pcs_slist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #ifdef WIN32 3 | # include 4 | #else 5 | # include 6 | #endif 7 | 8 | #include "pcs_mem.h" 9 | #include "pcs_slist.h" 10 | 11 | PCS_API PcsSList *pcs_slist_create() 12 | { 13 | PcsSList *res = 0; 14 | res = (PcsSList *)pcs_malloc(sizeof(PcsSList)); 15 | if (res) 16 | memset(res, 0, sizeof(PcsSList)); 17 | return res; 18 | } 19 | 20 | PCS_API PcsSList *pcs_slist_create_ex(const char *src, int len) 21 | { 22 | PcsSList *res = pcs_slist_create(); 23 | if (res) { 24 | if (len == -1) len = strlen(src); 25 | res->string = (char *)pcs_malloc(len + 1); 26 | if (res->string) { 27 | memcpy(res->string, src, len); 28 | res->string[len] = '\0'; 29 | } 30 | else { 31 | pcs_free(res); 32 | res = 0; 33 | } 34 | } 35 | return res; 36 | } 37 | 38 | PCS_API void pcs_slist_destroy(PcsSList *slist) 39 | { 40 | PcsSList *p = slist, *p2; 41 | while(p) { 42 | p2 = p; 43 | p = p->next; 44 | if (p2->string) 45 | pcs_free(p2->string); 46 | pcs_free(p2); 47 | } 48 | } 49 | 50 | PCS_API PcsSList *pcs_slist_add_ex(PcsSList *slist, const char *src, int len) 51 | { 52 | PcsSList *p = pcs_slist_create_ex(src, len); 53 | if (p) { 54 | while(slist->next) { 55 | slist = slist->next; 56 | } 57 | slist->next = p; 58 | p->next = 0; 59 | } 60 | return p; 61 | } 62 | 63 | PCS_API PcsSList2 *pcs_slist2_create() 64 | { 65 | PcsSList2 *res = 0; 66 | res = (PcsSList2 *)pcs_malloc(sizeof(PcsSList2)); 67 | if (res) 68 | memset(res, 0, sizeof(PcsSList2)); 69 | return res; 70 | } 71 | 72 | PCS_API PcsSList2 *pcs_slist2_create_ex(const char *src1, int len1, const char *src2, int len2) 73 | { 74 | PcsSList2 *res = pcs_slist2_create(); 75 | if (res) { 76 | res->string1 = (char *)pcs_malloc(len1 + 1); 77 | if (res->string1) { 78 | memcpy(res->string1, src1, len1); 79 | res->string1[len1] = '\0'; 80 | } 81 | else { 82 | pcs_free(res); 83 | res = 0; 84 | return res; 85 | } 86 | res->string2 = (char *)pcs_malloc(len2 + 1); 87 | if (res->string2) { 88 | memcpy(res->string2, src2, len2); 89 | res->string2[len2] = '\0'; 90 | } 91 | else { 92 | pcs_free(res->string1); 93 | pcs_free(res); 94 | res = 0; 95 | return res; 96 | } 97 | } 98 | return res; 99 | } 100 | 101 | PCS_API void pcs_slist2_destroy(PcsSList2 *slist) 102 | { 103 | PcsSList2 *p = slist, *p2; 104 | while(p) { 105 | p2 = p; 106 | p = p->next; 107 | if (p2->string1) 108 | pcs_free(p2->string1); 109 | if (p2->string2) 110 | pcs_free(p2->string2); 111 | pcs_free(p2); 112 | } 113 | } 114 | 115 | PCS_API PcsSList2 *pcs_slist2_add_ex(PcsSList2 *slist, const char *src1, int len1, const char *src2, int len2) 116 | { 117 | PcsSList2 *p = pcs_slist2_create_ex(src1, len1, src2, len2); 118 | if (p) { 119 | while(slist->next) { 120 | slist = slist->next; 121 | } 122 | slist->next = p; 123 | p->next = 0; 124 | } 125 | return p; 126 | } 127 | 128 | PCS_API PcsSList2 *pcs_slist2_clone(PcsSList2 *slist) 129 | { 130 | PcsSList2 *newlist = 0, *p = slist, *n = 0; 131 | while (p) { 132 | if (n) { 133 | n = pcs_slist2_add_ex(n, p->string1, strlen(p->string1), p->string2, strlen(p->string2)); 134 | } 135 | else { 136 | n = newlist = pcs_slist2_create_ex(p->string1, strlen(p->string1), p->string2, strlen(p->string2)); 137 | } 138 | if (!n) { 139 | pcs_slist2_destroy(newlist); 140 | newlist = 0; 141 | break; 142 | } 143 | p = p->next; 144 | } 145 | return newlist; 146 | } 147 | 148 | -------------------------------------------------------------------------------- /pcs/pcs_slist.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_SLIST_H 2 | #define _PCS_SLIST_H 3 | 4 | /* 定义了字符串列表。列表以链表形式存储。 */ 5 | typedef struct PcsSList { 6 | char *string; 7 | struct PcsSList *next; 8 | } PcsSList; 9 | 10 | typedef struct PcsSList2 { 11 | char *string1; 12 | char *string2; 13 | struct PcsSList2 *next; 14 | } PcsSList2; 15 | 16 | PCS_API PcsSList *pcs_slist_create(); 17 | PCS_API PcsSList *pcs_slist_create_ex(const char *src, int len); 18 | PCS_API void pcs_slist_destroy(PcsSList *slist); 19 | PCS_API PcsSList *pcs_slist_add_ex(PcsSList *slist, const char *src, int len); 20 | 21 | PCS_API PcsSList2 *pcs_slist2_create(); 22 | PCS_API PcsSList2 *pcs_slist2_create_ex(const char *src1, int len1, const char *src2, int len2); 23 | PCS_API void pcs_slist2_destroy(PcsSList2 *slist); 24 | PCS_API PcsSList2 *pcs_slist2_add_ex(PcsSList2 *slist, const char *src, int len, const char *src2, int len2); 25 | PCS_API PcsSList2 *pcs_slist2_clone(PcsSList2 *slist); 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /pcs/pcs_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #ifdef WIN32 6 | # include 7 | # define snprintf _snprintf 8 | # define vsnprintf _vsnprintf 9 | #include "openssl_md5.h" 10 | #else 11 | # include 12 | #include 13 | #endif 14 | 15 | #include "pcs_mem.h" 16 | #include "pcs_utils.h" 17 | 18 | PCS_API PcsBool pcs_isLittleEndian() 19 | { 20 | union w { 21 | int a; 22 | char b; 23 | } c; 24 | c.a = 1; 25 | return (c.b == 1); 26 | } 27 | 28 | PCS_API PcsBool pcs_isBigEndian() 29 | { 30 | union w { 31 | int a; 32 | char b; 33 | } c; 34 | c.a = 1; 35 | return (c.b == 0); 36 | } 37 | 38 | PCS_API char *pcs_utils_strdup(const char *str) 39 | { 40 | char *res = 0; 41 | if (str) { 42 | res = (char *)pcs_malloc(strlen(str) + 1); 43 | if (!res) 44 | return 0; 45 | strcpy(res, str); 46 | } 47 | return res; 48 | } 49 | 50 | PCS_API char *pcs_utils_strcat(char *dst, const char *src, int src_len, int free_dst) 51 | { 52 | char *res = 0; 53 | int dst_len; 54 | 55 | if (!src) 56 | return dst; 57 | if (src_len == -1) 58 | src_len = strlen(src); 59 | if (src_len == 0) 60 | return dst; 61 | 62 | if (dst) 63 | dst_len = strlen(dst); 64 | else 65 | dst_len = 0; 66 | 67 | res = (char *)pcs_malloc(dst_len + src_len + 1); 68 | if (!res) 69 | return 0; 70 | memcpy(res, dst, dst_len); 71 | memcpy(res + dst_len, src, src_len); 72 | res[dst_len + src_len] = '\0'; 73 | if (dst && free_dst) 74 | pcs_free(dst); 75 | return res; 76 | } 77 | 78 | PCS_API char *pcs_utils_vsprintf(const char *fmt, va_list ap) 79 | { 80 | int cnt, sz=0; 81 | char *buf; 82 | va_list ap_try; 83 | 84 | #ifdef WIN32 85 | sz = 4096; 86 | #else 87 | sz = 1024; 88 | #endif 89 | buf = (char*)pcs_malloc(sz); 90 | try_print: 91 | va_copy(ap_try, ap); 92 | cnt = vsnprintf(buf, sz - 1, fmt, ap_try); 93 | va_end(ap_try); 94 | if (cnt > sz) { 95 | pcs_free(buf); 96 | sz *= 2; 97 | buf = (char*)pcs_malloc(sz); 98 | goto try_print; 99 | } 100 | if (cnt < 0) return NULL; 101 | buf[cnt] = '\0'; 102 | return buf; 103 | } 104 | 105 | PCS_API char *pcs_utils_sprintf(const char *fmt, ...) 106 | { 107 | char *res; 108 | va_list args; 109 | 110 | va_start(args, fmt); 111 | 112 | res = pcs_utils_vsprintf(fmt, args); 113 | 114 | va_end(args); 115 | return res; 116 | } 117 | 118 | /* Human-readable file size */ 119 | PCS_API char* pcs_utils_readable_size(double size/*in bytes*/, char *buf, int buf_size, char *sp) 120 | { 121 | int i = 0; 122 | const char* units[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; 123 | while (size > 1024) { 124 | size /= 1024; 125 | i++; 126 | } 127 | memset(buf, 0, buf_size); 128 | snprintf(buf, buf_size, "%.2f%s%s", (float)size, sp ? sp : "", units[i]); 129 | return buf; 130 | } 131 | 132 | /* Human-readable left time */ 133 | PCS_API char* pcs_utils_readable_left_time(int64_t second, char *buf, int buf_size, char *sp) 134 | { 135 | int day = (int)(second / (24 * 60 * 60)); 136 | int hour = (int)((second % (24 * 60 * 60)) / (60 * 60)); 137 | int minute = (int)(((second % (24 * 60 * 60)) % (60 * 60)) / 60); 138 | int sec = (int)(((second % (24 * 60 * 60)) % (60 * 60)) % 60); 139 | memset(buf, 0, buf_size); 140 | if (day > 0) { 141 | snprintf(buf, buf_size, "%d days %.2d:%.2d:%.2d", day, hour, minute, sec); 142 | } 143 | else { 144 | snprintf(buf, buf_size, "%.2d:%.2d:%.2d", hour, minute, sec); 145 | } 146 | return buf; 147 | } 148 | 149 | PCS_API char *pcs_utils_basedir(const char *path) 150 | { 151 | char *dir, *p; 152 | int i; 153 | i = strlen(path); 154 | dir = (char *) pcs_malloc(i + 1); 155 | if (!dir) 156 | return NULL; 157 | strcpy(dir, path); 158 | p = dir + i - 1; 159 | while(p > dir) { 160 | if (*p == '/' || *p == '\\') 161 | break; 162 | p--; 163 | } 164 | if (p == dir) { 165 | *p = '/'; 166 | p++; 167 | *p = '\0'; 168 | } else { 169 | *p = '\0'; 170 | } 171 | return dir; 172 | } 173 | 174 | PCS_API char *pcs_utils_filename(const char *path) 175 | { 176 | char *name; 177 | const char *p; 178 | int i; 179 | i = strlen(path); 180 | p = path + i - 1; 181 | while(p > path) { 182 | if (*p == '/' || *p == '\\') 183 | break; 184 | p--; 185 | } 186 | if (*p == '/' || *p == '\\') 187 | p++; 188 | i = strlen(p); 189 | name = (char *) pcs_malloc(i + 1); 190 | if (!name) 191 | return NULL; 192 | strcpy(name, p); 193 | return name; 194 | } 195 | 196 | static inline int chcmpi(char a, char b) 197 | { 198 | if((a == b) 199 | || ((a >= 'A' || a <= 'Z') && b == a + ('a' - 'A')) 200 | || ((a >= 'a' || a <= 'z') && b == a - ('a' - 'A'))) 201 | return 0; 202 | return a - b; 203 | } 204 | 205 | PCS_API int pcs_utils_strcmpi(const char *str1, const char *str2) 206 | { 207 | int r; 208 | const char *p1 = str1, 209 | *p2 = str2; 210 | while((*p1) && (*p2)) { 211 | r = chcmpi(*p1, *p2); 212 | if (r) return r; 213 | p1++; 214 | p2++; 215 | } 216 | return (*p1) - (*p2); 217 | } 218 | 219 | PCS_API PcsBool pcs_utils_streq(const char *str1, const char *str2, int len) 220 | { 221 | int i = 0; 222 | const char *p1 = str1, 223 | *p2 = str2; 224 | while((*p1) && (*p2) && (len == -1 || i < len)) { 225 | if ((*p1) != (*p2)) return PcsFalse; 226 | p1++; 227 | p2++; 228 | } 229 | return PcsTrue; 230 | } 231 | 232 | 233 | /** 234 | * 字符串md5 235 | */ 236 | PCS_API const char *pcs_md5_string(const char *str) 237 | { 238 | static char tmp[33] = { '\0' }; 239 | unsigned char md[16]; 240 | int i; 241 | MD5((const unsigned char*)str, strlen(str), md); 242 | for (i = 0; i<16; i++){ 243 | sprintf(&tmp[i * 2], "%02x", md[i]); 244 | } 245 | return tmp; 246 | } 247 | 248 | /** 249 | * 字符串md5。返回16字节的MD5值 250 | */ 251 | PCS_API const unsigned char *pcs_md5_string_raw(const char *str) 252 | { 253 | static unsigned char md[16]; 254 | MD5((const unsigned char*)str, strlen(str), md); 255 | return md; 256 | } 257 | 258 | PCS_API const unsigned char *pcs_md5_bytes_raw(const unsigned char* bytes, int len) 259 | { 260 | static unsigned char md[16]; 261 | MD5(bytes, len, md); 262 | return md; 263 | } 264 | 265 | PCS_API const char *pcs_md5_bytes(const unsigned char* bytes, int len) 266 | { 267 | static char tmp[33] = { '\0' }; 268 | unsigned char md[16]; 269 | int i; 270 | MD5(bytes, len, md); 271 | for (i = 0; i<16; i++){ 272 | sprintf(&tmp[i * 2], "%02x", md[i]); 273 | } 274 | return tmp; 275 | } 276 | 277 | 278 | ///** 279 | //* 字符串md5 280 | //*/ 281 | //PCS_API const char *md5_string_salt(const char *str, const char *salt) 282 | //{ 283 | // char *s; 284 | // int l = 0; 285 | // if (str) l += strlen(str); 286 | // if (salt) l += strlen(salt); 287 | // s = (char *)pcs_malloc(l + 1); 288 | // s[0] = '\0'; 289 | // if (str) strcat(s, str); 290 | // if (salt) strcat(s, salt); 291 | // return md5_string(s); 292 | //} 293 | 294 | /** 295 | * 文件 md5 296 | */ 297 | PCS_API const char *pcs_md5_file_s(const char *file_name) 298 | { 299 | static char tmp[33] = { '\0' }; 300 | MD5_CTX md5; 301 | unsigned char md[16]; 302 | int length, i; 303 | char buffer[1024]; 304 | FILE *file; 305 | MD5_Init(&md5); 306 | file = fopen(file_name, "rb"); 307 | if (!file) { 308 | printf("%s can't be openedn", file_name); 309 | return 0; 310 | } 311 | while ((length = fread(buffer, 1, 1024, file))) 312 | MD5_Update(&md5, buffer, length); 313 | MD5_Final(md, &md5); 314 | fclose(file); 315 | for (i = 0; i<16; i++){ 316 | sprintf(&tmp[i * 2], "%02x", md[i]); 317 | } 318 | return tmp; 319 | } 320 | 321 | /*把32位整数按从高位到低位顺序填充到buf的4个字节中。 322 | * 例:0xF1E2D3C4 填充后 buf[0] = 0xF1, buf[1] = 0xE2, buf[2] = 0xD3, buf[3] = 0xC4.buf中其他项无改动 323 | */ 324 | void int2Buffer(int v, char *buf) 325 | { 326 | buf[0] = (unsigned char)((((unsigned int)v) >> 24) & 0xFF); 327 | buf[1] = (unsigned char)((((unsigned int)v) >> 16) & 0xFF); 328 | buf[2] = (unsigned char)((((unsigned int)v) >> 8) & 0xFF); 329 | buf[3] = (unsigned char)(((unsigned int)v) & 0xFF); 330 | } 331 | 332 | /*int2Buffer的逆过程*/ 333 | int readInt(const char *buf) 334 | { 335 | unsigned int rc = 0; 336 | rc = (unsigned int)(((unsigned char)buf[0])); 337 | rc = (unsigned int)((rc << 8) | ((unsigned char)buf[1])); 338 | rc = (unsigned int)((rc << 8) | ((unsigned char)buf[2])); 339 | rc = (unsigned int)((rc << 8) | ((unsigned char)buf[3])); 340 | return rc; 341 | } 342 | 343 | /* 344 | * 提取出字符 callback({...}) 中的 {...} 部分 345 | */ 346 | char *extract_json_from_callback(char *callback) 347 | { 348 | char *start, *p; 349 | start = callback; 350 | while ((*start) && ((*start) != '(') && ((*start) != '{')) { 351 | start++; 352 | } 353 | if ((*start) == '{') return start; 354 | if ((*start) != '(') return NULL; 355 | start++; 356 | p = start; 357 | while (*p) p++; 358 | while ((p >= start) && (*p != ')')) p--; 359 | if ((*p) == ')') { 360 | *p = '\0'; 361 | return start; 362 | } 363 | return NULL; 364 | } 365 | 366 | /* For C# invoke */ 367 | PCS_API int pcs_strlen(const char *s) 368 | { 369 | return strlen(s); 370 | } 371 | 372 | /*时间转换*/ 373 | PCS_API const char *pcs_time2str(time_t time) 374 | { 375 | struct tm *tm = NULL; 376 | time_t t = time; 377 | static char tmp[64]; 378 | 379 | if (time) 380 | tm = localtime(&t); 381 | 382 | if (tm) { 383 | sprintf(tmp, "%d-%02d-%02d %02d:%02d:%02d", 384 | 1900 + tm->tm_year, 385 | tm->tm_mon + 1, 386 | tm->tm_mday, 387 | tm->tm_hour, 388 | tm->tm_min, 389 | tm->tm_sec); 390 | return tmp; 391 | } 392 | else { 393 | return ""; 394 | } 395 | } 396 | 397 | /* 等同 javascript 中的 '(new Date()).getTime()'。 */ 398 | PCS_API int64_t pcs_jstime() 399 | { 400 | int64_t sec, usec; 401 | #if defined(_WIN32) 402 | static int mode = 0; 403 | static int64_t addsec = 0, freq = 1; 404 | BOOL retval; 405 | int64_t qpc; 406 | if (mode == 0) { 407 | retval = QueryPerformanceFrequency((LARGE_INTEGER*)&freq); 408 | freq = (freq == 0) ? 1 : freq; 409 | retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc); 410 | addsec = (int64_t)time(NULL); 411 | addsec = addsec - (int64_t)((qpc / freq) & 0x7fffffff); 412 | mode = 1; 413 | } 414 | retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc); 415 | retval = retval * 2; 416 | sec = (qpc / freq) + addsec; 417 | usec = ((qpc % freq) * 1000000 / freq); 418 | #else 419 | struct timeval time; 420 | gettimeofday(&time, NULL); 421 | sec = time.tv_sec; 422 | usec = time.tv_usec; 423 | #endif 424 | return sec * 1000 + usec / 1000; 425 | } 426 | 427 | PCS_API char *pcs_js_timestr() 428 | { 429 | static char s[32]; 430 | int64_t tm = pcs_jstime(); 431 | snprintf(s, sizeof(s), "%" PRId64, tm); 432 | return s; 433 | } 434 | 435 | -------------------------------------------------------------------------------- /pcs/pcs_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_UTILS_H 2 | #define _PCS_UTILS_H 3 | 4 | #include 5 | 6 | #include "pcs_defs.h" 7 | #include "pcs_slist.h" 8 | 9 | /*返回当前处理器是否是大端模式*/ 10 | PCS_API PcsBool pcs_isLittleEndian(); 11 | /*返回当前处理器是否是小端模式*/ 12 | PCS_API PcsBool pcs_isBigEndian(); 13 | 14 | /*原因复制一份字符串。返回值需要调用pcs_free()*/ 15 | PCS_API char *pcs_utils_strdup(const char *str); 16 | /* 把 src 添加到 dst 后边,自动重建 dst。 17 | * 返回 新建立的 字符串指针。 18 | * free_dst 设置为 TRUE,表示建立新的字符串后,释放掉 dst 的内存空间。 19 | */ 20 | PCS_API char *pcs_utils_strcat(char *dst, const char *src, int src_len, int free_dst); 21 | /*pcs_utils_sprintf的矢量模式*/ 22 | PCS_API char *pcs_utils_vsprintf(const char *fmt, va_list ap); 23 | /*输出字符串到内存,并返回该内存。*/ 24 | PCS_API char *pcs_utils_sprintf(const char *fmt, ...); 25 | /*格式化size为容易读写模式*/ 26 | PCS_API char *pcs_utils_readable_size(double size/*in bytes*/, char *buf, int buf_size, char *sp); 27 | PCS_API char* pcs_utils_readable_left_time(int64_t second, char *buf, int buf_size, char *sp); 28 | /*获取path的父目录*/ 29 | PCS_API char *pcs_utils_basedir(const char *path); 30 | /*获取path中文件名部分*/ 31 | PCS_API char *pcs_utils_filename(const char *path); 32 | /*忽略大小写比较两个字符串。 str1 < str2时返回负数;str1 == str2时返回0;str1 > str2时返回正数。*/ 33 | PCS_API int pcs_utils_strcmpi(const char *str1, const char *str2); 34 | /*判断两字符串是否相等。相等返回PcsTrue,否则返回PcsFalse。只比较len指定的长度。*/ 35 | PCS_API PcsBool pcs_utils_streq(const char *str1, const char *str2, int len); 36 | 37 | /*计算字节的MD5值*/ 38 | PCS_API const unsigned char *pcs_md5_bytes_raw(const unsigned char* bytes, int len); 39 | 40 | /*计算字节的MD5值*/ 41 | PCS_API const char *pcs_md5_bytes(const unsigned char* bytes, int len); 42 | 43 | /** 44 | * 字符串md5 45 | */ 46 | PCS_API const char *pcs_md5_string(const char *str); 47 | /** 48 | * 字符串md5。返回16字节的MD5值 49 | */ 50 | PCS_API const unsigned char *pcs_md5_string_raw(const char *str); 51 | /** 52 | * 文件 md5 53 | */ 54 | PCS_API const char *pcs_md5_file_s(const char *file_name); 55 | 56 | /*把32位整数按从高位到低位顺序填充到buf的4个字节中。 57 | * 例:0xF1E2D3C4 填充后 buf[0] = 0xF1, buf[1] = 0xE2, buf[2] = 0xD3, buf[3] = 0xC4.buf中其他项无改动 58 | */ 59 | void int2Buffer(int v, char *buf); 60 | 61 | /*int2Buffer的逆过程*/ 62 | int readInt(const char *buf); 63 | 64 | /* 65 | * 提取出字符 callback({...}) 中的 {...} 部分 66 | */ 67 | char *extract_json_from_callback(char *callback); 68 | 69 | PCS_API int pcs_strlen(const char *s); 70 | 71 | PCS_API const char *pcs_time2str(time_t time); 72 | 73 | /* 等同 javascript 中的 '(new Date()).getTime()'。 */ 74 | PCS_API int64_t pcs_jstime(); 75 | 76 | PCS_API char *pcs_js_timestr(); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /pcs/utf8.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTF8_H 2 | #define _UTF8_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | 11 | /* is c the start of a utf8 sequence? */ 12 | #define isutf(c) (((c)&0xC0)!=0x80) 13 | 14 | /* convert UTF-8 data to wide character */ 15 | int u8_toucs(wchar_t *dest, int sz, const char *src, int srcsz); 16 | 17 | /* return the min size that can store the wide character, not include '\0'-terminated. mean: return_value = wcslen() * sizeof(wchar_t) */ 18 | int u8_wc_size(const char *src, int srcsz); 19 | 20 | /* the opposite conversion */ 21 | int u8_toutf8(char *dest, int sz, const wchar_t *src, int srcsz); 22 | 23 | /* return the min size that can store the UTF-8 codes, not include '\0'-terminated. mean: return_value = strlen(UTF-8 codes) */ 24 | int u8_size(const wchar_t *src, int srcsz); 25 | 26 | /* single character to UTF-8 */ 27 | int u8_wc_toutf8(char *dest, wchar_t ch); 28 | 29 | /* character number to byte offset 找到第charnum个字符的开始位置,str是utf8编码的一串字符,往后移动charnum个字符,实际移动的字节数量即是返回值 */ 30 | int u8_offset(const char *str, int charnum); 31 | 32 | /* byte offset to character number 找到offset字节中包含的字符数量,s是utf8编码的一串字符,往后移动offset个字节,实际移动的字符数量即是返回值 */ 33 | int u8_charnum(const char *s, int offset); 34 | 35 | /* return next character, updating an index variable */ 36 | wchar_t u8_nextchar(const char *s, int *i); 37 | 38 | /* move to next character */ 39 | void u8_inc(const char *s, int *i); 40 | 41 | /* move to previous character */ 42 | void u8_dec(const char *s, int *i); 43 | 44 | /* returns length of next utf-8 sequence */ 45 | int u8_seqlen(const char *s); 46 | 47 | /* assuming src points to the character after a backslash, read an 48 | escape sequence, storing the result in dest and returning the number of 49 | input characters processed */ 50 | int u8_read_escape_sequence(const char *src, wchar_t *dest); 51 | 52 | /* given a wide character, convert it to an ASCII escape sequence stored in 53 | buf, where buf is "sz" bytes. returns the number of characters output. */ 54 | int u8_escape_wchar(char *buf, int sz, wchar_t ch); 55 | 56 | /* convert a string "src" containing escape sequences to UTF-8 */ 57 | int u8_unescape(char *buf, int sz, const char *src); 58 | 59 | /* convert UTF-8 "src" to ASCII with escape sequences. 60 | if escape_quotes is nonzero, quote characters will be preceded by 61 | backslashes as well. */ 62 | int u8_escape(char *buf, int sz, const char *src, int escape_quotes); 63 | 64 | /* utility predicates used by the above */ 65 | int octal_digit(char c); 66 | int hex_digit(char c); 67 | 68 | /* return a pointer to the first occurrence of ch in s, or NULL if not 69 | found. character index of found character returned in *charn. */ 70 | char *u8_strchr(const char *s, wchar_t ch, int *charn); 71 | 72 | /* same as the above, but searches a buffer of a given size instead of 73 | a NUL-terminated string. */ 74 | char *u8_memchr(const char *s, wchar_t ch, int sz, int *charn); 75 | 76 | /* count the number of characters in a UTF-8 string */ 77 | int u8_strlen(const char *s); 78 | 79 | int u8_is_locale_utf8(const char *locale); 80 | 81 | /* printf where the format string and arguments may be in UTF-8. 82 | you can avoid this function and just use ordinary printf() if the current 83 | locale is UTF-8. */ 84 | int u8_vprintf(const char *fmt, va_list ap); 85 | int u8_printf(const char *fmt, ...); 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /pcs_shell.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {BE157AEB-7F3E-4C6F-8C8E-192D57E37A11} 15 | Win32Proj 16 | pcs 17 | 8.1 18 | 19 | 20 | 21 | Application 22 | true 23 | v140_xp 24 | MultiByte 25 | 26 | 27 | Application 28 | false 29 | v140_xp 30 | true 31 | MultiByte 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | pcs 46 | .exe 47 | 48 | 49 | false 50 | pcs 51 | .exe 52 | 53 | 54 | 55 | 56 | 57 | Level3 58 | Disabled 59 | CURL_STATICLIB;LIBCONFIG_STATIC;PCRE_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) 60 | $(SolutionDir)deps\include;%(AdditionalIncludeDirectories) 61 | MultiThreadedDLL 62 | /utf-8 %(AdditionalOptions) 63 | 64 | 65 | Console 66 | true 67 | $(SolutionDir)deps\lib\$(PlatformTarget);%(AdditionalLibraryDirectories) 68 | libcurl_a.lib;Shlwapi.lib;%(AdditionalDependencies) 69 | libcmt.lib 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Level3 79 | 80 | 81 | MaxSpeed 82 | true 83 | true 84 | CURL_STATICLIB;LIBCONFIG_STATIC;PCRE_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) 85 | $(SolutionDir)deps\include;%(AdditionalIncludeDirectories) 86 | MultiThreadedDLL 87 | /utf-8 %(AdditionalOptions) 88 | 89 | 90 | Console 91 | true 92 | true 93 | true 94 | $(SolutionDir)deps\lib\$(PlatformTarget);%(AdditionalLibraryDirectories) 95 | libcurl_a.lib;Shlwapi.lib;%(AdditionalDependencies) 96 | libcmt.lib 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /pcs_shell.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {e155cd81-86dc-4a87-b15f-0c5d9aa4fa70} 18 | 19 | 20 | {b4fc2e4d-4d1e-42bd-93f9-96d9578f2a5a} 21 | 22 | 23 | {388e605c-56bc-4776-97b7-f94fec898409} 24 | 25 | 26 | {0c047a36-4680-427c-9b8d-ef8145e7291b} 27 | 28 | 29 | 30 | 31 | Source Files\pcs 32 | 33 | 34 | Source Files\pcs 35 | 36 | 37 | Source Files\pcs 38 | 39 | 40 | Source Files\pcs 41 | 42 | 43 | Source Files\pcs 44 | 45 | 46 | Source Files\pcs 47 | 48 | 49 | Source Files\pcs 50 | 51 | 52 | Source Files\pcs 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files\rb_tree 65 | 66 | 67 | Source Files\rb_tree 68 | 69 | 70 | Source Files\rb_tree 71 | 72 | 73 | Source Files 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Source Files\pcs 83 | 84 | 85 | Source Files\pcs 86 | 87 | 88 | Source Files\pcs 89 | 90 | 91 | Source Files 92 | 93 | 94 | 95 | 96 | Header Files\pcs 97 | 98 | 99 | Header Files\pcs 100 | 101 | 102 | Header Files\pcs 103 | 104 | 105 | Header Files\pcs 106 | 107 | 108 | Header Files\pcs 109 | 110 | 111 | Header Files\pcs 112 | 113 | 114 | Header Files\pcs 115 | 116 | 117 | Header Files\pcs 118 | 119 | 120 | Header Files\pcs 121 | 122 | 123 | Header Files\pcs 124 | 125 | 126 | Header Files\pcs 127 | 128 | 129 | Header Files 130 | 131 | 132 | Header Files 133 | 134 | 135 | Header Files 136 | 137 | 138 | Header Files\rb_tree 139 | 140 | 141 | Header Files\rb_tree 142 | 143 | 144 | Header Files\rb_tree 145 | 146 | 147 | Header Files 148 | 149 | 150 | Header Files 151 | 152 | 153 | Header Files\pcs 154 | 155 | 156 | Header Files 157 | 158 | 159 | Header Files\pcs 160 | 161 | 162 | Header Files\pcs 163 | 164 | 165 | Header Files\pcs 166 | 167 | 168 | Header Files 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /rb_tree/CHANGES: -------------------------------------------------------------------------------- 1 | 2 | Sun Jan 09, 2005: I fixed a bug that caused the test_rb program to 3 | go into an infinite loop if the user entered an 4 | invalid key. Thanks to Amores Perros for pointing 5 | out this problem. 6 | 7 | Wed Sep 19, 2001: I fixed some bugs and memory leaks pointed out 8 | by Brett Donahue and added some rudimentary 9 | memory checking tests to the makefile. 10 | 11 | -------------------------------------------------------------------------------- /rb_tree/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Redistribution and use in source and binary forms, with or without 3 | modification, are permitted provided that neither the name of Emin 4 | Martinian nor the names of any contributors are be used to endorse or 5 | promote products derived from this software without specific prior 6 | written permission. 7 | 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 9 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 10 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 11 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 12 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 13 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 14 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 15 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 16 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 17 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 18 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | -------------------------------------------------------------------------------- /rb_tree/makefile.txt: -------------------------------------------------------------------------------- 1 | 2 | # prompt> make 3 | # builds everything and links in test program test_rb 4 | # 5 | # prompt> make mem_check 6 | # Rebuilds everything using dmalloc and does memory testing. 7 | # Only works if you have dmalloc installed (see http://dmalloc.com). 8 | 9 | SRCS = test_red_black_tree.c red_black_tree.c stack.c misc.c 10 | 11 | HDRS = red_black_tree.h stack.h misc.h 12 | 13 | OBJS = red_black_tree.o stack.o test_red_black_tree.o misc.o 14 | 15 | CC = gcc 16 | 17 | CFLAGS = -g -Wall -pedantic 18 | 19 | PROGRAM = test_rb 20 | 21 | .PHONY: mem_check clean 22 | 23 | all: $(PROGRAM) 24 | 25 | $(PROGRAM): $(OBJS) 26 | $(CC) $(CFLAGS) $(OBJS) -o $(PROGRAM) $(DMALLOC_LIB) 27 | 28 | mem_check: 29 | @if [ -e makefile.txt ] ; then \ 30 | echo "Using makefile.txt" ; \ 31 | $(MAKE) clean -f makefile.txt ; \ 32 | $(MAKE) $(PROGRAM) "CFLAGS=$(CFLAGS) -DDMALLOC" "DMALLOC_LIB=-ldmalloc" -f makefile.txt ; \ 33 | else \ 34 | echo "Using default makefile (i.e. no -f flag)." ; \ 35 | $(MAKE) clean ; \ 36 | $(MAKE) $(PROGRAM) "CFLAGS=$(CFLAGS) -DDMALLOC" "DMALLOC_LIB=-ldmalloc" ; \ 37 | fi 38 | ./simple_test.sh 39 | @if [ -s unfreed.txt ] ; then \ 40 | echo " " ; \ 41 | echo "Leaked some memory. See logfile for details." ;\ 42 | else \ 43 | echo " " ; \ 44 | echo "No memory leaks detected. " ;\ 45 | echo " " ; \ 46 | echo "Test passed. " ; \ 47 | echo " " ; \ 48 | fi 49 | 50 | 51 | test_red_black_tree.o: test_red_black_tree.c red_black_tree.c stack.c stack.h red_black_tree.h misc.h 52 | 53 | red_black_tree.o: red_black_tree.h stack.h red_black_tree.c stack.c misc.h misc.c 54 | 55 | stack.o: stack.c stack.h misc.h misc.c 56 | 57 | clean: 58 | rm -f *.o *~ $(PROGRAM) 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /rb_tree/misc.c: -------------------------------------------------------------------------------- 1 | #include "misc.h" 2 | 3 | /***********************************************************************/ 4 | /* FUNCTION: void Assert(int assertion, char* error) */ 5 | /**/ 6 | /* INPUTS: assertion should be a predicated that the programmer */ 7 | /* assumes to be true. If this assumption is not true the message */ 8 | /* error is printed and the program exits. */ 9 | /**/ 10 | /* OUTPUT: None. */ 11 | /**/ 12 | /* Modifies input: none */ 13 | /**/ 14 | /* Note: If DEBUG_ASSERT is not defined then assertions should not */ 15 | /* be in use as they will slow down the code. Therefore the */ 16 | /* compiler will complain if an assertion is used when */ 17 | /* DEBUG_ASSERT is undefined. */ 18 | /***********************************************************************/ 19 | 20 | 21 | void Assert(int assertion, char* error) { 22 | if(!assertion) { 23 | printf("Assertion Failed: %s\n",error); 24 | exit(-1); 25 | } 26 | } 27 | 28 | 29 | 30 | /***********************************************************************/ 31 | /* FUNCTION: SafeMalloc */ 32 | /**/ 33 | /* INPUTS: size is the size to malloc */ 34 | /**/ 35 | /* OUTPUT: returns pointer to allocated memory if succesful */ 36 | /**/ 37 | /* EFFECT: mallocs new memory. If malloc fails, prints error message */ 38 | /* and terminates program. */ 39 | /**/ 40 | /* Modifies Input: none */ 41 | /**/ 42 | /***********************************************************************/ 43 | 44 | void * SafeMalloc(size_t size) { 45 | void * result; 46 | 47 | if ( (result = malloc(size)) ) { /* assignment intentional */ 48 | return(result); 49 | } else { 50 | printf("memory overflow: malloc failed in SafeMalloc."); 51 | printf(" Exiting Program.\n"); 52 | exit(-1); 53 | return(0); 54 | } 55 | } 56 | /* NullFunction does nothing it is included so that it can be passed */ 57 | /* as a function to RBTreeCreate when no other suitable function has */ 58 | /* been defined */ 59 | 60 | void NullFunction(void * junk) { ; } 61 | -------------------------------------------------------------------------------- /rb_tree/misc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifndef INC_E_MISC_ 5 | #define INC_E_MISC_ 6 | 7 | 8 | /* CONVENTIONS: All data structures for red-black trees have the prefix */ 9 | /* "rb_" to prevent name conflicts. */ 10 | /* */ 11 | /* Function names: Each word in a function name begins with */ 12 | /* a capital letter. An example funcntion name is */ 13 | /* CreateRedTree(a,b,c). Furthermore, each function name */ 14 | /* should begin with a capital letter to easily distinguish */ 15 | /* them from variables. */ 16 | /* */ 17 | /* Variable names: Each word in a variable name begins with */ 18 | /* a capital letter EXCEPT the first letter of the variable */ 19 | /* name. For example, int newLongInt. Global variables have */ 20 | /* names beginning with "g". An example of a global */ 21 | /* variable name is gNewtonsConstant. */ 22 | 23 | void Assert(int assertion, char* error); 24 | void * SafeMalloc(size_t size); 25 | 26 | #endif 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /rb_tree/red_black_tree.h: -------------------------------------------------------------------------------- 1 | #ifdef DMALLOC 2 | #include 3 | #endif 4 | #include"misc.h" 5 | #include"stack.h" 6 | 7 | /* Source: http://web.mit.edu/~emin/www.old/source_code/red_black_tree/index.html */ 8 | 9 | /* CONVENTIONS: All data structures for red-black trees have the prefix */ 10 | /* "rb_" to prevent name conflicts. */ 11 | /* */ 12 | /* Function names: Each word in a function name begins with */ 13 | /* a capital letter. An example funcntion name is */ 14 | /* CreateRedTree(a,b,c). Furthermore, each function name */ 15 | /* should begin with a capital letter to easily distinguish */ 16 | /* them from variables. */ 17 | /* */ 18 | /* Variable names: Each word in a variable name begins with */ 19 | /* a capital letter EXCEPT the first letter of the variable */ 20 | /* name. For example, int newLongInt. Global variables have */ 21 | /* names beginning with "g". An example of a global */ 22 | /* variable name is gNewtonsConstant. */ 23 | 24 | /* comment out the line below to remove all the debugging assertion */ 25 | /* checks from the compiled code. */ 26 | #define DEBUG_ASSERT 1 27 | 28 | typedef struct rb_red_blk_node { 29 | void* key; 30 | void* info; 31 | int red; /* if red=0 then the node is black */ 32 | struct rb_red_blk_node* left; 33 | struct rb_red_blk_node* right; 34 | struct rb_red_blk_node* parent; 35 | } rb_red_blk_node; 36 | 37 | 38 | /* Compare(a,b) should return 1 if *a > *b, -1 if *a < *b, and 0 otherwise */ 39 | /* Destroy(a) takes a pointer to whatever key might be and frees it accordingly */ 40 | typedef struct rb_red_blk_tree { 41 | int (*Compare)(const void* a, const void* b, void *state); 42 | void (*DestroyKey)(void* a, void *state); 43 | void (*DestroyInfo)(void* a, void *state); 44 | void (*PrintKey)(const void* a, void *state); 45 | void (*PrintInfo)(void* a, void *state); 46 | int (*EnumerateInfo)(void*, void*); /*返回0表示继续执行,返回非0值表示中断执行。*/ 47 | void *compareState; 48 | void *destroyKeyState; 49 | void *destroyInfoState; 50 | void *printKeyState; 51 | void *printInfoState; 52 | void *enumerateInfoState; 53 | /* A sentinel is used for root and for nil. These sentinels are */ 54 | /* created when RBTreeCreate is caled. root->left should always */ 55 | /* point to the node which is the root of the tree. nil points to a */ 56 | /* node which should always be black but has aribtrary children and */ 57 | /* parent and no key or info. The point of using these sentinels is so */ 58 | /* that the root and nil nodes do not require special cases in the code */ 59 | rb_red_blk_node* root; 60 | rb_red_blk_node* nil; 61 | } rb_red_blk_tree; 62 | 63 | rb_red_blk_tree* RBTreeCreate(int (*CompFunc)(const void*, const void*, void*), 64 | void (*DestFunc)(void*, void*), 65 | void (*InfoDestFunc)(void*, void*), 66 | void (*PrintFunc)(const void*, void*), 67 | void (*PrintInfo)(void*, void*)); 68 | rb_red_blk_node * RBTreeInsert(rb_red_blk_tree*, void* key, void* info); 69 | void RBTreePrint(rb_red_blk_tree*); 70 | int RBTreeEnumerateInfo(rb_red_blk_tree* tree); 71 | void RBDelete(rb_red_blk_tree* , rb_red_blk_node* ); 72 | void RBTreeDestroy(rb_red_blk_tree*); 73 | rb_red_blk_node* TreePredecessor(rb_red_blk_tree*,rb_red_blk_node*); 74 | rb_red_blk_node* TreeSuccessor(rb_red_blk_tree*,rb_red_blk_node*); 75 | rb_red_blk_node* RBExactQuery(rb_red_blk_tree*, void*); 76 | stk_stack * RBEnumerate(rb_red_blk_tree* tree,void* low, void* high); 77 | void NullFunction(void*); 78 | -------------------------------------------------------------------------------- /rb_tree/stack.c: -------------------------------------------------------------------------------- 1 | #include "stack.h" 2 | 3 | int StackNotEmpty(stk_stack * theStack) { 4 | return( theStack ? ((int)((long) theStack->top)) : 0); 5 | } 6 | 7 | stk_stack * StackJoin(stk_stack * stack1, stk_stack * stack2) { 8 | if (!stack1->tail) { 9 | free(stack1); 10 | return(stack2); 11 | } else { 12 | stack1->tail->next=stack2->top; 13 | stack1->tail=stack2->tail; 14 | free(stack2); 15 | return(stack1); 16 | } 17 | } 18 | 19 | stk_stack * StackCreate() { 20 | stk_stack * newStack; 21 | 22 | newStack=(stk_stack *) SafeMalloc(sizeof(stk_stack)); 23 | newStack->top=newStack->tail=NULL; 24 | return(newStack); 25 | } 26 | 27 | 28 | void StackPush(stk_stack * theStack, DATA_TYPE newInfoPointer) { 29 | stk_stack_node * newNode; 30 | 31 | if(!theStack->top) { 32 | newNode=(stk_stack_node *) SafeMalloc(sizeof(stk_stack_node)); 33 | newNode->info=newInfoPointer; 34 | newNode->next=theStack->top; 35 | theStack->top=newNode; 36 | theStack->tail=newNode; 37 | } else { 38 | newNode=(stk_stack_node *) SafeMalloc(sizeof(stk_stack_node)); 39 | newNode->info=newInfoPointer; 40 | newNode->next=theStack->top; 41 | theStack->top=newNode; 42 | } 43 | 44 | } 45 | 46 | DATA_TYPE StackPop(stk_stack * theStack) { 47 | DATA_TYPE popInfo; 48 | stk_stack_node * oldNode; 49 | 50 | if(theStack->top) { 51 | popInfo=theStack->top->info; 52 | oldNode=theStack->top; 53 | theStack->top=theStack->top->next; 54 | free(oldNode); 55 | if (!theStack->top) theStack->tail=NULL; 56 | } else { 57 | popInfo=NULL; 58 | } 59 | return(popInfo); 60 | } 61 | 62 | void StackDestroy(stk_stack * theStack,void DestFunc(void * a)) { 63 | stk_stack_node * x=theStack->top; 64 | stk_stack_node * y; 65 | 66 | if(theStack) { 67 | while(x) { 68 | y=x->next; 69 | DestFunc(x->info); 70 | free(x); 71 | x=y; 72 | } 73 | free(theStack); 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /rb_tree/stack.h: -------------------------------------------------------------------------------- 1 | #include "misc.h" 2 | 3 | /* CONVENTIONS: All data structures for stacks have the prefix */ 4 | /* "stk_" to prevent name conflicts. */ 5 | /* */ 6 | /* Function names: Each word in a function name begins with */ 7 | /* a capital letter. An example funcntion name is */ 8 | /* CreateRedTree(a,b,c). Furthermore, each function name */ 9 | /* should begin with a capital letter to easily distinguish */ 10 | /* them from variables. */ 11 | /* */ 12 | /* Variable names: Each word in a variable name begins with */ 13 | /* a capital letter EXCEPT the first letter of the variable */ 14 | /* name. For example, int newLongInt. Global variables have */ 15 | /* names beginning with "g". An example of a global */ 16 | /* variable name is gNewtonsConstant. */ 17 | 18 | /* if DATA_TYPE is undefined then stack.h and stack.c will be code for */ 19 | /* stacks of void *, if they are defined then they will be stacks of the */ 20 | /* appropriate data_type */ 21 | 22 | #ifndef DATA_TYPE 23 | #define DATA_TYPE void * 24 | #endif 25 | 26 | typedef struct stk_stack_node { 27 | DATA_TYPE info; 28 | struct stk_stack_node * next; 29 | } stk_stack_node; 30 | 31 | typedef struct stk_stack { 32 | stk_stack_node * top; 33 | stk_stack_node * tail; 34 | } stk_stack ; 35 | 36 | /* These functions are all very straightforward and self-commenting so */ 37 | /* I didn't think additional comments would be useful */ 38 | stk_stack * StackJoin(stk_stack * stack1, stk_stack * stack2); 39 | stk_stack * StackCreate(); 40 | void StackPush(stk_stack * theStack, DATA_TYPE newInfoPointer); 41 | void * StackPop(stk_stack * theStack); 42 | int StackNotEmpty(stk_stack *); 43 | 44 | -------------------------------------------------------------------------------- /rb_tree/test_red_black_tree.c: -------------------------------------------------------------------------------- 1 | #include"red_black_tree.h" 2 | #include 3 | #include 4 | 5 | 6 | /* this file has functions to test a red-black tree of integers */ 7 | 8 | void IntDest(void* a) { 9 | free((int*)a); 10 | } 11 | 12 | 13 | 14 | int IntComp(const void* a,const void* b) { 15 | if( *(int*)a > *(int*)b) return(1); 16 | if( *(int*)a < *(int*)b) return(-1); 17 | return(0); 18 | } 19 | 20 | void IntPrint(const void* a) { 21 | printf("%i",*(int*)a); 22 | } 23 | 24 | void InfoPrint(void* a) { 25 | ; 26 | } 27 | 28 | void InfoDest(void *a){ 29 | ; 30 | } 31 | 32 | int main() { 33 | stk_stack* enumResult; 34 | int option=0; 35 | int newKey,newKey2; 36 | int* newInt; 37 | rb_red_blk_node* newNode; 38 | rb_red_blk_tree* tree; 39 | 40 | tree=RBTreeCreate(IntComp,IntDest,InfoDest,IntPrint,InfoPrint); 41 | while(option!=8) { 42 | printf("choose one of the following:\n"); 43 | printf("(1) add to tree\n(2) delete from tree\n(3) query\n"); 44 | printf("(4) find predecessor\n(5) find sucessor\n(6) enumerate\n"); 45 | printf("(7) print tree\n(8) quit\n"); 46 | do option=fgetc(stdin); while(-1 != option && isspace(option)); 47 | option-='0'; 48 | switch(option) 49 | { 50 | case 1: 51 | { 52 | printf("type key for new node\n"); 53 | scanf("%i",&newKey); 54 | newInt=(int*) malloc(sizeof(int)); 55 | *newInt=newKey; 56 | RBTreeInsert(tree,newInt,0); 57 | } 58 | break; 59 | 60 | case 2: 61 | { 62 | printf("type key of node to remove\n"); 63 | scanf("%i",&newKey); 64 | if ( ( newNode=RBExactQuery(tree,&newKey ) ) ) RBDelete(tree,newNode);/*assignment*/ 65 | else printf("key not found in tree, no action taken\n"); 66 | } 67 | break; 68 | 69 | case 3: 70 | { 71 | printf("type key of node to query for\n"); 72 | scanf("%i",&newKey); 73 | if ( ( newNode = RBExactQuery(tree,&newKey) ) ) {/*assignment*/ 74 | printf("data found in tree at location %i\n",(int)newNode); 75 | } else { 76 | printf("data not in tree\n"); 77 | } 78 | } 79 | break; 80 | case 4: 81 | { 82 | printf("type key of node to find predecessor of\n"); 83 | scanf("%i",&newKey); 84 | if ( ( newNode = RBExactQuery(tree,&newKey) ) ) {/*assignment*/ 85 | newNode=TreePredecessor(tree,newNode); 86 | if(tree->nil == newNode) { 87 | printf("there is no predecessor for that node (it is a minimum)\n"); 88 | } else { 89 | printf("predecessor has key %i\n",*(int*)newNode->key); 90 | } 91 | } else { 92 | printf("data not in tree\n"); 93 | } 94 | } 95 | break; 96 | case 5: 97 | { 98 | printf("type key of node to find successor of\n"); 99 | scanf("%i",&newKey); 100 | if ( (newNode = RBExactQuery(tree,&newKey) ) ) { 101 | newNode=TreeSuccessor(tree,newNode); 102 | if(tree->nil == newNode) { 103 | printf("there is no successor for that node (it is a maximum)\n"); 104 | } else { 105 | printf("successor has key %i\n",*(int*)newNode->key); 106 | } 107 | } else { 108 | printf("data not in tree\n"); 109 | } 110 | } 111 | break; 112 | case 6: 113 | { 114 | printf("type low and high keys to see all keys between them\n"); 115 | scanf("%i %i",&newKey,&newKey2); 116 | enumResult=RBEnumerate(tree,&newKey,&newKey2); 117 | while ( (newNode = StackPop(enumResult)) ) { 118 | tree->PrintKey(newNode->key); 119 | printf("\n"); 120 | } 121 | free(enumResult); 122 | } 123 | break; 124 | case 7: 125 | { 126 | RBTreePrint(tree); 127 | } 128 | break; 129 | case 8: 130 | { 131 | RBTreeDestroy(tree); 132 | return 0; 133 | } 134 | break; 135 | default: 136 | printf("Invalid input; Please try again.\n"); 137 | } 138 | } 139 | return 0; 140 | } 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /shell.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_SHELL_SHELL_H 2 | #define _PCS_SHELL_SHELL_H 3 | 4 | #include 5 | #include "pcs/pcs.h" 6 | 7 | #define SORT_DIRECTION_ASC 0 /*正序*/ 8 | #define SORT_DIRECTION_DESC 1 /*倒序*/ 9 | 10 | 11 | /* shell 的上下文 */ 12 | typedef struct ShellContext 13 | { 14 | char *contextfile; /*上下文文件的路径*/ 15 | char *cookiefile; /*Cookie文件路径*/ 16 | char *captchafile; /*验证码图片路径*/ 17 | char *workdir; /*当前工作目录*/ 18 | Pcs pcs; 19 | 20 | int list_page_size; /*执行list命令时,每页大小*/ 21 | char *list_sort_name; /*执行list命令时,排序字段,可选值:name|time|size*/ 22 | char *list_sort_direction; /*执行list命令时,排序字段,可选值:asc|desc*/ 23 | 24 | char *secure_method; /*加密方法,可选值:plaintext|aes-cbc-128|aes-cbc-192|aes-cbc-256*/ 25 | char *secure_key; /*加密时的KEY*/ 26 | int secure_enable; /*是否启用加密*/ 27 | 28 | int timeout_retry; /*是否启用超时后重试*/ 29 | int max_thread; /*指定最大线程数量*/ 30 | int max_speed_per_thread; /*指定单个线程的最多下载速度*/ 31 | int max_upload_speed_per_thread; /*指定单个线程的最大上传速度*/ 32 | int cache_size; /* 磁盘缓存的大小 */ 33 | char *user_agent; /**/ 34 | } ShellContext; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _PCS_SHELL_UTILS_H 2 | #define _PCS_SHELL_UTILS_H 3 | 4 | /* 5 | * 从标准输入中读入字符到 str 中,直到遇到回车或者达到 size 限定。 6 | * 字符回显。 7 | * str - 输入的字符串将填充到 str 中 8 | * size - 最多输入 size 个字节。 9 | * 当达到 size 限定后,函数会设置 str[size - 1] = '\0'。 10 | */ 11 | void std_string(char *str, int size); 12 | 13 | /* 14 | * 从标准输入中读入字符到 password 中,直到遇到回车或者达到 size 限定。 15 | * 字符不回显。 16 | * password - 输入的密码将填充到 password 中 17 | * size - 最多输入size个字节。 18 | * 当达到 size 限定后,函数会设置 str[size - 1] = '\0'。 19 | */ 20 | void std_password(char *password, int size); 21 | 22 | /* 23 | * 返回path是否是一个绝对路径。 24 | * 对于Windows系统: 满足正则: ^[a-zA-Z]\: 25 | * 对于非Windows系统: 满足正则:^[~|/] 26 | */ 27 | int is_absolute_path(const char *path); 28 | 29 | /** detecting whether base is starts with str 30 | */ 31 | int startsWith(char* base, char* str); 32 | 33 | /** detecting whether base is ends with str 34 | */ 35 | int endsWith(char* base, char* str); 36 | 37 | /* 38 | * 判断两个字符串是否相等。 39 | * s1 - 以'\0'为结束标记的字符串 40 | * s2 - 待比较的字符串 41 | * s2len - s2字符串的字节长度。如果传入-1的话,则使用'\0'作为其结束标记 42 | * 如果相等,则返回1,否则返回0。 43 | */ 44 | int streq(const char *s1, const char *s2, int s2len); 45 | 46 | /* 47 | * 判断arr数组中是否存在字符串str,如果存在则返回其标号(标号为 [索引] + 1),否则返回0。 48 | * 比较时区分大小写。 49 | * arr - 存储很多字符串的数组,数组最后一个元素必须为NULL。 50 | * str - 判断是否存在的字符串 51 | * len - 字符串长度。 如果传入-1,则'\0'作为其结束标记。 52 | */ 53 | int str_in_array(const char **arr, const char *str, int len); 54 | 55 | /* 56 | * 合并路径,如果filename传入的是绝对路径,则直接返回filename的拷贝。 57 | * 编译时,如果定义WIN32,则使用'\\'作为目录分隔符,否则使用'/'作为目录分隔符。 58 | * base - 基目录 59 | * basesz - base的字节长度,传入-1的话,将使用strlen()函数读取。 60 | * filename - 文件名字 61 | * 使用完后,需调用pcs_free来释放返回值 62 | */ 63 | char *combin_path(const char *base, int basesz, const char *filename); 64 | 65 | /* 66 | * 合并网盘路径,如果filename传入的是绝对路径,则直接返回filename的拷贝。 67 | * 该函数会使用'/'替换所有'\\'。 68 | * 使用完后,需调用pcs_free来释放返回值 69 | */ 70 | char *combin_net_disk_path(const char *base, const char *filename); 71 | 72 | /* 73 | * 修正路径为*nix格式。 74 | * 即把路径中'\\'替换为'/'。 75 | * 修正完成后,原样返回path指针 76 | */ 77 | char *fix_unix_path(char *path); 78 | 79 | /* 80 | * 修正路径。 81 | * 即把路径中斜杠替换为反斜杠。 82 | * 修正完成后,原样返回path 83 | */ 84 | char *fix_win_path(char *path); 85 | 86 | /* 87 | * 读取文件全部内容 88 | * file - 待读取的文件 89 | * pBuffer - 文件的内容所在的内存指针将存入pBuffer指定的内存中 90 | * 返回读取到的字节大小。使用完成后,需调用pcs_free(*pBuffer) 91 | */ 92 | int read_file(const char *file, char **pBuffer); 93 | 94 | /* 95 | 从程序路径中找到文件名开始的位置, 96 | 返回开始位置的指针 97 | */ 98 | const char *filename(const char *path); 99 | 100 | /* 101 | * 获取路径的父路径,如果没有父路径则返回NULL。 102 | * path - 当前路径 103 | * len - path的字节长度,如果传入-1,则内部使用strlen()获取其长度 104 | * 返回值需要调用pcs_free() 105 | */ 106 | char *base_dir(const char *path, int len); 107 | 108 | /* 109 | string to time_t 110 | 时间格式 2009-3-24 0:00:08 或 2009-3-24 111 | */ 112 | int str2time(const char *str, time_t *timeData); 113 | 114 | /* 115 | time_t to string 时间格式 2009-3-24 0:00:08 116 | */ 117 | char *time2str(char *buf, const time_t *t); 118 | 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | #ifndef _VERSION_H 2 | #define _VERSION_H 3 | 4 | #ifdef PRG_VER 5 | # define program_version PRG_VER 6 | #else 7 | # define program_version "v0.3.1" 8 | #endif 9 | 10 | #define program_name "pcs" 11 | #ifdef PCS_API_VERSION 12 | # define program_api_version " (API " PCS_API_VERSION ")" 13 | #else 14 | # define program_api_version 15 | #endif 16 | #if defined(DEBUG) || defined(_DEBUG) 17 | # define program_full_name program_name "(debug) " program_version program_api_version 18 | #else 19 | # define program_full_name program_name " " program_version program_api_version 20 | #endif 21 | 22 | #endif 23 | --------------------------------------------------------------------------------