├── README.md ├── http_server ├── Makefile ├── cJSON.c ├── cJSON.h └── http_server.c ├── https_server ├── Makefile ├── cJSON.c ├── cJSON.h ├── https-common.c ├── https-common.h ├── https-server.c ├── server-certificate-chain.pem └── server-private-key.pem ├── login ├── cJSON.cpp ├── cJSON.h └── login.cpp └── login_https ├── cJSON.cpp ├── cJSON.h └── login.cpp /README.md: -------------------------------------------------------------------------------- 1 | # libcurl 2 | 用libcurl实现http和https服务 3 | -------------------------------------------------------------------------------- /http_server/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC=gcc 3 | CPPFLAGS= -I. -I./include 4 | CFLAGS=-Wall 5 | LIBS=-lpthread -levent -lm 6 | 7 | #找到当前目录下所有的.c文件 8 | src = $(wildcard *.c) 9 | 10 | #将当前目录下所有的.c 转换成.o给obj 11 | obj = $(patsubst %.c, %.o, $(src)) 12 | 13 | 14 | server=server 15 | 16 | target=$(server) 17 | 18 | 19 | ALL:$(target) 20 | 21 | 22 | #生成所有的.o文件 23 | $(obj):%.o:%.c 24 | $(CC) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) 25 | 26 | 27 | #test_main程序 28 | $(server): http_server.o cJSON.o 29 | $(CC) $^ -o $@ $(LIBS) 30 | 31 | 32 | 33 | 34 | 35 | #clean指令 36 | 37 | clean: 38 | -rm -rf $(obj) $(target) 39 | 40 | distclean: 41 | -rm -rf $(obj) $(target) 42 | 43 | #将clean目标 改成一个虚拟符号 44 | .PHONY: clean ALL distclean 45 | -------------------------------------------------------------------------------- /http_server/cJSON.c: -------------------------------------------------------------------------------- 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 | /* cJSON */ 24 | /* JSON parser in C. */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "cJSON.h" 34 | 35 | static const char *ep; 36 | 37 | const char *cJSON_GetErrorPtr(void) {return ep;} 38 | 39 | static int cJSON_strcasecmp(const char *s1,const char *s2) 40 | { 41 | if (!s1) return (s1==s2)?0:1;if (!s2) return 1; 42 | for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; 43 | return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); 44 | } 45 | 46 | static void *(*cJSON_malloc)(size_t sz) = malloc; 47 | static void (*cJSON_free)(void *ptr) = free; 48 | 49 | static char* cJSON_strdup(const char* str) 50 | { 51 | size_t len; 52 | char* copy; 53 | 54 | len = strlen(str) + 1; 55 | if (!(copy = (char*)cJSON_malloc(len))) return 0; 56 | memcpy(copy,str,len); 57 | return copy; 58 | } 59 | 60 | void cJSON_InitHooks(cJSON_Hooks* hooks) 61 | { 62 | if (!hooks) { /* Reset hooks */ 63 | cJSON_malloc = malloc; 64 | cJSON_free = free; 65 | return; 66 | } 67 | 68 | cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 69 | cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 70 | } 71 | 72 | /* Internal constructor. */ 73 | static cJSON *cJSON_New_Item(void) 74 | { 75 | cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 76 | if (node) memset(node,0,sizeof(cJSON)); 77 | return node; 78 | } 79 | 80 | /* Delete a cJSON structure. */ 81 | void cJSON_Delete(cJSON *c) 82 | { 83 | cJSON *next; 84 | while (c) 85 | { 86 | next=c->next; 87 | if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 88 | if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 89 | if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); 90 | cJSON_free(c); 91 | c=next; 92 | } 93 | } 94 | 95 | /* Parse the input text to generate a number, and populate the result into item. */ 96 | static const char *parse_number(cJSON *item,const char *num) 97 | { 98 | double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; 99 | 100 | if (*num=='-') sign=-1,num++; /* Has sign? */ 101 | if (*num=='0') num++; /* is zero */ 102 | if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ 103 | if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ 104 | if (*num=='e' || *num=='E') /* Exponent? */ 105 | { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ 106 | while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ 107 | } 108 | 109 | n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 110 | 111 | item->valuedouble=n; 112 | item->valueint=(int)n; 113 | item->type=cJSON_Number; 114 | return num; 115 | } 116 | 117 | static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } 118 | 119 | typedef struct {char *buffer; int length; int offset; } printbuffer; 120 | 121 | static char* ensure(printbuffer *p,int needed) 122 | { 123 | char *newbuffer;int newsize; 124 | if (!p || !p->buffer) return 0; 125 | needed+=p->offset; 126 | if (needed<=p->length) return p->buffer+p->offset; 127 | 128 | newsize=pow2gt(needed); 129 | newbuffer=(char*)cJSON_malloc(newsize); 130 | if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} 131 | if (newbuffer) memcpy(newbuffer,p->buffer,p->length); 132 | cJSON_free(p->buffer); 133 | p->length=newsize; 134 | p->buffer=newbuffer; 135 | return newbuffer+p->offset; 136 | } 137 | 138 | static int update(printbuffer *p) 139 | { 140 | char *str; 141 | if (!p || !p->buffer) return 0; 142 | str=p->buffer+p->offset; 143 | return p->offset+strlen(str); 144 | } 145 | 146 | /* Render the number nicely from the given item into a string. */ 147 | static char *print_number(cJSON *item,printbuffer *p) 148 | { 149 | char *str=0; 150 | double d=item->valuedouble; 151 | if (d==0) 152 | { 153 | if (p) str=ensure(p,2); 154 | else str=(char*)cJSON_malloc(2); /* special case for 0. */ 155 | if (str) strcpy(str,"0"); 156 | } 157 | else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 158 | { 159 | if (p) str=ensure(p,21); 160 | else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ 161 | if (str) sprintf(str,"%d",item->valueint); 162 | } 163 | else 164 | { 165 | if (p) str=ensure(p,64); 166 | else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ 167 | if (str) 168 | { 169 | if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); 170 | else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); 171 | else sprintf(str,"%f",d); 172 | } 173 | } 174 | return str; 175 | } 176 | 177 | static unsigned parse_hex4(const char *str) 178 | { 179 | unsigned h=0; 180 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 181 | h=h<<4;str++; 182 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 183 | h=h<<4;str++; 184 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 185 | h=h<<4;str++; 186 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 187 | return h; 188 | } 189 | 190 | /* Parse the input text into an unescaped cstring, and populate item. */ 191 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 192 | static const char *parse_string(cJSON *item,const char *str) 193 | { 194 | const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; 195 | if (*str!='\"') {ep=str;return 0;} /* not a string! */ 196 | 197 | while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ 198 | 199 | out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 200 | if (!out) return 0; 201 | 202 | ptr=str+1;ptr2=out; 203 | while (*ptr!='\"' && *ptr) 204 | { 205 | if (*ptr!='\\') *ptr2++=*ptr++; 206 | else 207 | { 208 | ptr++; 209 | switch (*ptr) 210 | { 211 | case 'b': *ptr2++='\b'; break; 212 | case 'f': *ptr2++='\f'; break; 213 | case 'n': *ptr2++='\n'; break; 214 | case 'r': *ptr2++='\r'; break; 215 | case 't': *ptr2++='\t'; break; 216 | case 'u': /* transcode utf16 to utf8. */ 217 | uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ 218 | 219 | if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ 220 | 221 | if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ 222 | { 223 | if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ 224 | uc2=parse_hex4(ptr+3);ptr+=6; 225 | if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ 226 | uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 227 | } 228 | 229 | len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; 230 | 231 | switch (len) { 232 | case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 233 | case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 234 | case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 235 | case 1: *--ptr2 =(uc | firstByteMark[len]); 236 | } 237 | ptr2+=len; 238 | break; 239 | default: *ptr2++=*ptr; break; 240 | } 241 | ptr++; 242 | } 243 | } 244 | *ptr2=0; 245 | if (*ptr=='\"') ptr++; 246 | item->valuestring=out; 247 | item->type=cJSON_String; 248 | return ptr; 249 | } 250 | 251 | /* Render the cstring provided to an escaped version that can be printed. */ 252 | static char *print_string_ptr(const char *str,printbuffer *p) 253 | { 254 | const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; 255 | 256 | for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; 257 | if (!flag) 258 | { 259 | len=ptr-str; 260 | if (p) out=ensure(p,len+3); 261 | else out=(char*)cJSON_malloc(len+3); 262 | if (!out) return 0; 263 | ptr2=out;*ptr2++='\"'; 264 | strcpy(ptr2,str); 265 | ptr2[len]='\"'; 266 | ptr2[len+1]=0; 267 | return out; 268 | } 269 | 270 | if (!str) 271 | { 272 | if (p) out=ensure(p,3); 273 | else out=(char*)cJSON_malloc(3); 274 | if (!out) return 0; 275 | strcpy(out,"\"\""); 276 | return out; 277 | } 278 | ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} 279 | 280 | if (p) out=ensure(p,len+3); 281 | else out=(char*)cJSON_malloc(len+3); 282 | if (!out) return 0; 283 | 284 | ptr2=out;ptr=str; 285 | *ptr2++='\"'; 286 | while (*ptr) 287 | { 288 | if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; 289 | else 290 | { 291 | *ptr2++='\\'; 292 | switch (token=*ptr++) 293 | { 294 | case '\\': *ptr2++='\\'; break; 295 | case '\"': *ptr2++='\"'; break; 296 | case '\b': *ptr2++='b'; break; 297 | case '\f': *ptr2++='f'; break; 298 | case '\n': *ptr2++='n'; break; 299 | case '\r': *ptr2++='r'; break; 300 | case '\t': *ptr2++='t'; break; 301 | default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ 302 | } 303 | } 304 | } 305 | *ptr2++='\"';*ptr2++=0; 306 | return out; 307 | } 308 | /* Invote print_string_ptr (which is useful) on an item. */ 309 | static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} 310 | 311 | /* Predeclare these prototypes. */ 312 | static const char *parse_value(cJSON *item,const char *value); 313 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); 314 | static const char *parse_array(cJSON *item,const char *value); 315 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); 316 | static const char *parse_object(cJSON *item,const char *value); 317 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); 318 | 319 | /* Utility to jump whitespace and cr/lf */ 320 | static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} 321 | 322 | /* Parse an object - create a new root, and populate. */ 323 | cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) 324 | { 325 | const char *end=0; 326 | cJSON *c=cJSON_New_Item(); 327 | ep=0; 328 | if (!c) return 0; /* memory fail */ 329 | 330 | end=parse_value(c,skip(value)); 331 | if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ 332 | 333 | /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 334 | if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} 335 | if (return_parse_end) *return_parse_end=end; 336 | return c; 337 | } 338 | /* Default options for cJSON_Parse */ 339 | cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} 340 | 341 | /* Render a cJSON item/entity/structure to text. */ 342 | char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} 343 | char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} 344 | 345 | char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) 346 | { 347 | printbuffer p; 348 | p.buffer=(char*)cJSON_malloc(prebuffer); 349 | p.length=prebuffer; 350 | p.offset=0; 351 | return print_value(item,0,fmt,&p); 352 | return p.buffer; 353 | } 354 | 355 | 356 | /* Parser core - when encountering text, process appropriately. */ 357 | static const char *parse_value(cJSON *item,const char *value) 358 | { 359 | if (!value) return 0; /* Fail on null. */ 360 | if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } 361 | if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 362 | if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } 363 | if (*value=='\"') { return parse_string(item,value); } 364 | if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } 365 | if (*value=='[') { return parse_array(item,value); } 366 | if (*value=='{') { return parse_object(item,value); } 367 | 368 | ep=value;return 0; /* failure. */ 369 | } 370 | 371 | /* Render a value to text. */ 372 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) 373 | { 374 | char *out=0; 375 | if (!item) return 0; 376 | if (p) 377 | { 378 | switch ((item->type)&255) 379 | { 380 | case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} 381 | case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} 382 | case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} 383 | case cJSON_Number: out=print_number(item,p);break; 384 | case cJSON_String: out=print_string(item,p);break; 385 | case cJSON_Array: out=print_array(item,depth,fmt,p);break; 386 | case cJSON_Object: out=print_object(item,depth,fmt,p);break; 387 | } 388 | } 389 | else 390 | { 391 | switch ((item->type)&255) 392 | { 393 | case cJSON_NULL: out=cJSON_strdup("null"); break; 394 | case cJSON_False: out=cJSON_strdup("false");break; 395 | case cJSON_True: out=cJSON_strdup("true"); break; 396 | case cJSON_Number: out=print_number(item,0);break; 397 | case cJSON_String: out=print_string(item,0);break; 398 | case cJSON_Array: out=print_array(item,depth,fmt,0);break; 399 | case cJSON_Object: out=print_object(item,depth,fmt,0);break; 400 | } 401 | } 402 | return out; 403 | } 404 | 405 | /* Build an array from input text. */ 406 | static const char *parse_array(cJSON *item,const char *value) 407 | { 408 | cJSON *child; 409 | if (*value!='[') {ep=value;return 0;} /* not an array! */ 410 | 411 | item->type=cJSON_Array; 412 | value=skip(value+1); 413 | if (*value==']') return value+1; /* empty array. */ 414 | 415 | item->child=child=cJSON_New_Item(); 416 | if (!item->child) return 0; /* memory fail */ 417 | value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 418 | if (!value) return 0; 419 | 420 | while (*value==',') 421 | { 422 | cJSON *new_item; 423 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 424 | child->next=new_item;new_item->prev=child;child=new_item; 425 | value=skip(parse_value(child,skip(value+1))); 426 | if (!value) return 0; /* memory fail */ 427 | } 428 | 429 | if (*value==']') return value+1; /* end of array */ 430 | ep=value;return 0; /* malformed. */ 431 | } 432 | 433 | /* Render an array to text */ 434 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) 435 | { 436 | char **entries; 437 | char *out=0,*ptr,*ret;int len=5; 438 | cJSON *child=item->child; 439 | int numentries=0,i=0,fail=0; 440 | size_t tmplen=0; 441 | 442 | /* How many entries in the array? */ 443 | while (child) numentries++,child=child->next; 444 | /* Explicitly handle numentries==0 */ 445 | if (!numentries) 446 | { 447 | if (p) out=ensure(p,3); 448 | else out=(char*)cJSON_malloc(3); 449 | if (out) strcpy(out,"[]"); 450 | return out; 451 | } 452 | 453 | if (p) 454 | { 455 | /* Compose the output array. */ 456 | i=p->offset; 457 | ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; 458 | child=item->child; 459 | while (child && !fail) 460 | { 461 | print_value(child,depth+1,fmt,p); 462 | p->offset=update(p); 463 | if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} 464 | child=child->next; 465 | } 466 | ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; 467 | out=(p->buffer)+i; 468 | } 469 | else 470 | { 471 | /* Allocate an array to hold the values for each */ 472 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 473 | if (!entries) return 0; 474 | memset(entries,0,numentries*sizeof(char*)); 475 | /* Retrieve all the results: */ 476 | child=item->child; 477 | while (child && !fail) 478 | { 479 | ret=print_value(child,depth+1,fmt,0); 480 | entries[i++]=ret; 481 | if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 482 | child=child->next; 483 | } 484 | 485 | /* If we didn't fail, try to malloc the output string */ 486 | if (!fail) out=(char*)cJSON_malloc(len); 487 | /* If that fails, we fail. */ 488 | if (!out) fail=1; 489 | 490 | /* Handle failure. */ 491 | if (fail) 492 | { 493 | for (i=0;itype=cJSON_Object; 520 | value=skip(value+1); 521 | if (*value=='}') return value+1; /* empty array. */ 522 | 523 | item->child=child=cJSON_New_Item(); 524 | if (!item->child) return 0; 525 | value=skip(parse_string(child,skip(value))); 526 | if (!value) return 0; 527 | child->string=child->valuestring;child->valuestring=0; 528 | if (*value!=':') {ep=value;return 0;} /* fail! */ 529 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 530 | if (!value) return 0; 531 | 532 | while (*value==',') 533 | { 534 | cJSON *new_item; 535 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 536 | child->next=new_item;new_item->prev=child;child=new_item; 537 | value=skip(parse_string(child,skip(value+1))); 538 | if (!value) return 0; 539 | child->string=child->valuestring;child->valuestring=0; 540 | if (*value!=':') {ep=value;return 0;} /* fail! */ 541 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 542 | if (!value) return 0; 543 | } 544 | 545 | if (*value=='}') return value+1; /* end of array */ 546 | ep=value;return 0; /* malformed. */ 547 | } 548 | 549 | /* Render an object to text. */ 550 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) 551 | { 552 | char **entries=0,**names=0; 553 | char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 554 | cJSON *child=item->child; 555 | int numentries=0,fail=0; 556 | size_t tmplen=0; 557 | /* Count the number of entries. */ 558 | while (child) numentries++,child=child->next; 559 | /* Explicitly handle empty object case */ 560 | if (!numentries) 561 | { 562 | if (p) out=ensure(p,fmt?depth+4:3); 563 | else out=(char*)cJSON_malloc(fmt?depth+4:3); 564 | if (!out) return 0; 565 | ptr=out;*ptr++='{'; 566 | if (fmt) {*ptr++='\n';for (i=0;ioffset; 574 | len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; 575 | *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; 576 | child=item->child;depth++; 577 | while (child) 578 | { 579 | if (fmt) 580 | { 581 | ptr=ensure(p,depth); if (!ptr) return 0; 582 | for (j=0;joffset+=depth; 584 | } 585 | print_string_ptr(child->string,p); 586 | p->offset=update(p); 587 | 588 | len=fmt?2:1; 589 | ptr=ensure(p,len); if (!ptr) return 0; 590 | *ptr++=':';if (fmt) *ptr++='\t'; 591 | p->offset+=len; 592 | 593 | print_value(child,depth,fmt,p); 594 | p->offset=update(p); 595 | 596 | len=(fmt?1:0)+(child->next?1:0); 597 | ptr=ensure(p,len+1); if (!ptr) return 0; 598 | if (child->next) *ptr++=','; 599 | if (fmt) *ptr++='\n';*ptr=0; 600 | p->offset+=len; 601 | child=child->next; 602 | } 603 | ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; 604 | if (fmt) for (i=0;ibuffer)+i; 607 | } 608 | else 609 | { 610 | /* Allocate space for the names and the objects */ 611 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 612 | if (!entries) return 0; 613 | names=(char**)cJSON_malloc(numentries*sizeof(char*)); 614 | if (!names) {cJSON_free(entries);return 0;} 615 | memset(entries,0,sizeof(char*)*numentries); 616 | memset(names,0,sizeof(char*)*numentries); 617 | 618 | /* Collect all the results into our arrays: */ 619 | child=item->child;depth++;if (fmt) len+=depth; 620 | while (child) 621 | { 622 | names[i]=str=print_string_ptr(child->string,0); 623 | entries[i++]=ret=print_value(child,depth,fmt,0); 624 | if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 625 | child=child->next; 626 | } 627 | 628 | /* Try to allocate the output string */ 629 | if (!fail) out=(char*)cJSON_malloc(len); 630 | if (!out) fail=1; 631 | 632 | /* Handle failure */ 633 | if (fail) 634 | { 635 | for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} 662 | cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} 663 | cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} 664 | 665 | /* Utility for array list handling. */ 666 | static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} 667 | /* Utility for handling references. */ 668 | static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 669 | 670 | /* Add item to array/object. */ 671 | void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} 672 | void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} 673 | void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} 674 | void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} 675 | void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} 676 | 677 | cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; 678 | if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} 679 | void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} 680 | cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} 681 | void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} 682 | 683 | /* Replace array/object items with new ones. */ 684 | void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} 685 | newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} 686 | void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; 687 | newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; 688 | if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} 689 | void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} 690 | 691 | /* Create basic types: */ 692 | cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} 693 | cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} 694 | cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} 695 | cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} 696 | cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} 697 | cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} 698 | cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} 699 | cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} 700 | 701 | /* Create Arrays: */ 702 | cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 703 | cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 704 | cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 705 | cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 706 | 707 | /* Duplication */ 708 | cJSON *cJSON_Duplicate(cJSON *item,int recurse) 709 | { 710 | cJSON *newitem,*cptr,*nptr=0,*newchild; 711 | /* Bail on bad ptr */ 712 | if (!item) return 0; 713 | /* Create new item */ 714 | newitem=cJSON_New_Item(); 715 | if (!newitem) return 0; 716 | /* Copy over all vars */ 717 | newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; 718 | if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} 719 | if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} 720 | /* If non-recursive, then we're done! */ 721 | if (!recurse) return newitem; 722 | /* Walk the ->next chain for the child. */ 723 | cptr=item->child; 724 | while (cptr) 725 | { 726 | newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ 727 | if (!newchild) {cJSON_Delete(newitem);return 0;} 728 | if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 729 | else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ 730 | cptr=cptr->next; 731 | } 732 | return newitem; 733 | } 734 | 735 | void cJSON_Minify(char *json) 736 | { 737 | char *into=json; 738 | while (*json) 739 | { 740 | if (*json==' ') json++; 741 | else if (*json=='\t') json++; /* Whitespace characters. */ 742 | else if (*json=='\r') json++; 743 | else if (*json=='\n') json++; 744 | else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ 745 | else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ 746 | else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ 747 | else *into++=*json++; /* All other characters. */ 748 | } 749 | *into=0; /* and null-terminate. */ 750 | } 751 | -------------------------------------------------------------------------------- /http_server/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 | #define cJSON_StringIsConst 512 42 | 43 | /* The cJSON structure: */ 44 | typedef struct cJSON { 45 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 46 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 47 | 48 | int type; /* The type of the item, as above. */ 49 | 50 | char *valuestring; /* The item's string, if type==cJSON_String */ 51 | int valueint; /* 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 | /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ 73 | extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); 74 | /* Delete a cJSON entity and all subentities. */ 75 | extern void cJSON_Delete(cJSON *c); 76 | 77 | /* Returns the number of items in an array (or object). */ 78 | extern int cJSON_GetArraySize(cJSON *array); 79 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 80 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 81 | /* Get item "string" from object. Case insensitive. */ 82 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 83 | 84 | /* 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. */ 85 | extern const char *cJSON_GetErrorPtr(void); 86 | 87 | /* These calls create a cJSON item of the appropriate type. */ 88 | extern cJSON *cJSON_CreateNull(void); 89 | extern cJSON *cJSON_CreateTrue(void); 90 | extern cJSON *cJSON_CreateFalse(void); 91 | extern cJSON *cJSON_CreateBool(int b); 92 | extern cJSON *cJSON_CreateNumber(double num); 93 | extern cJSON *cJSON_CreateString(const char *string); 94 | extern cJSON *cJSON_CreateArray(void); 95 | extern cJSON *cJSON_CreateObject(void); 96 | 97 | /* These utilities create an Array of count items. */ 98 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 99 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 100 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 101 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 102 | 103 | /* Append item to the specified array/object. */ 104 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 105 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 106 | extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ 107 | /* 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. */ 108 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 109 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 110 | 111 | /* Remove/Detatch items from Arrays/Objects. */ 112 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 113 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 114 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 115 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 116 | 117 | /* Update array items. */ 118 | extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ 119 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 120 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 121 | 122 | /* Duplicate a cJSON item */ 123 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 124 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 125 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 126 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 127 | 128 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 129 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 130 | 131 | extern void cJSON_Minify(char *json); 132 | 133 | /* Macros for creating things quickly. */ 134 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 135 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 136 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 137 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 138 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 139 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 140 | 141 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 142 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 143 | #define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 144 | 145 | #ifdef __cplusplus 146 | } 147 | #endif 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /http_server/http_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include //for getopt, fork 4 | #include //for strcat 5 | //for struct evkeyvalq 6 | #include 7 | #include 8 | //for http 9 | //#include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define MYHTTPD_SIGNATURE "MoCarHttpd v0.1" 18 | 19 | //处理模块 20 | void httpd_handler(struct evhttp_request *req, void *arg) { 21 | char output[2048] = "\0"; 22 | char tmp[1024]; 23 | 24 | //获取客户端请求的URI(使用evhttp_request_uri或直接req->uri) 25 | const char *uri; 26 | uri = evhttp_request_uri(req); 27 | #if 0 28 | sprintf(tmp, "uri=%s\n", uri);// /data?cmd=new... 29 | strcat(output, tmp); 30 | #endif 31 | 32 | sprintf(tmp, "uri=%s\n", req->uri); 33 | strcat(output, tmp); 34 | 35 | //decoded uri 36 | char *decoded_uri; 37 | decoded_uri = evhttp_decode_uri(uri); 38 | sprintf(tmp, "decoded_uri=%s\n", decoded_uri);// /data?cmd= newFile ... 39 | strcat(output, tmp); 40 | 41 | //http://127.0.0.1:8080/username=gailun&passwd=123123 42 | 43 | //解析URI的参数(即GET方法的参数) 44 | struct evkeyvalq params;//key ---value, key2--- value2// cmd --- newfile fromId == 0 45 | //将URL数据封装成key-value格式,q=value1, s=value2 46 | evhttp_parse_query(decoded_uri, ¶ms); 47 | 48 | //得到q所对应的value 49 | sprintf(tmp, "username=%s\n", evhttp_find_header(¶ms, "username")); 50 | strcat(output, tmp); 51 | //得到s所对应的value 52 | sprintf(tmp, "passwd=%s\n", evhttp_find_header(¶ms, "passwd")); 53 | strcat(output, tmp); 54 | 55 | free(decoded_uri); 56 | 57 | //获取POST方法的数据 58 | char *post_data = (char *) EVBUFFER_DATA(req->input_buffer); 59 | sprintf(tmp, "post_data=%s\n", post_data); 60 | strcat(output, tmp); 61 | 62 | 63 | /* 64 | 具体的:可以根据GET/POST的参数执行相应操作,然后将结果输出 65 | ... 66 | */ 67 | //入库 68 | 69 | 70 | 71 | /* 输出到客户端 */ 72 | 73 | //HTTP header 74 | evhttp_add_header(req->output_headers, "Server", MYHTTPD_SIGNATURE); 75 | evhttp_add_header(req->output_headers, "Content-Type", "text/plain; charset=UTF-8"); 76 | evhttp_add_header(req->output_headers, "Connection", "close"); 77 | 78 | //输出的内容 79 | struct evbuffer *buf; 80 | buf = evbuffer_new(); 81 | evbuffer_add_printf(buf, "It works!\n%s\n", output); 82 | 83 | //将封装好的evbuffer 发送给客户端 84 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 85 | 86 | evbuffer_free(buf); 87 | 88 | } 89 | 90 | //处理模块 91 | void login_handler(struct evhttp_request *req, void *arg) { 92 | 93 | printf("got connection "); 94 | 95 | char request_data[4096] = {0}; 96 | 97 | //获取POST方法的数据 98 | size_t post_size = EVBUFFER_LENGTH(req->input_buffer); 99 | char *post_data = (char *) EVBUFFER_DATA(req->input_buffer); 100 | memcpy(request_data, post_data, post_size); 101 | printf("post_data = [%s], len =%ld\n", post_data, post_size); 102 | 103 | 104 | 105 | char username[256] = {0}; 106 | char password[256] = {0}; 107 | char isDriver[10] = {0}; 108 | /* 109 | 具体的:可以根据GET/POST的参数执行相应操作,然后将结果输出 110 | ... 111 | */ 112 | 113 | /* 114 | 115 | ====给服务端的协议==== 116 | http://ip:port/login [json_data] 117 | { 118 | username: "gailun", 119 | password: "123123", 120 | driver: "yes" 121 | } 122 | * 123 | * 124 | * */ 125 | cJSON *root = cJSON_Parse(request_data); 126 | 127 | 128 | 129 | cJSON* username_obj = cJSON_GetObjectItem(root, "username"); 130 | strcpy(username, username_obj->valuestring); 131 | 132 | 133 | cJSON* password_obj = cJSON_GetObjectItem(root, "password"); 134 | strcpy(password, password_obj->valuestring); 135 | 136 | cJSON* isDriver_obj = cJSON_GetObjectItem(root, "driver"); 137 | strcpy(isDriver, isDriver_obj->valuestring); 138 | 139 | printf("username = %s, password = %s, isDriver = %s\n", username, password, isDriver); 140 | cJSON_Delete(root); 141 | printf("----\n"); 142 | 143 | 144 | //查询数据库 得到查询结果 145 | 146 | 147 | //给前段回复一个响应结果 148 | cJSON*response_root = cJSON_CreateObject(); 149 | 150 | cJSON_AddStringToObject(response_root, "result", "ok"); 151 | 152 | char *response_str = cJSON_Print(response_root); 153 | 154 | 155 | 156 | 157 | /* 输出到客户端 */ 158 | 159 | //HTTP header 160 | evhttp_add_header(req->output_headers, "Server", MYHTTPD_SIGNATURE); 161 | evhttp_add_header(req->output_headers, "Content-Type", "text/plain; charset=UTF-8"); 162 | evhttp_add_header(req->output_headers, "Connection", "close"); 163 | 164 | //输出的内容 165 | struct evbuffer *buf; 166 | buf = evbuffer_new(); 167 | evbuffer_add_printf(buf, "%s", response_str); 168 | 169 | //将封装好的evbuffer 发送给客户端 170 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 171 | 172 | evbuffer_free(buf); 173 | 174 | cJSON_Delete(response_root); 175 | free(response_str); 176 | } 177 | 178 | 179 | void show_help() { 180 | char *help = "http://localhost:8080\n" 181 | "-l interface to listen on, default is 0.0.0.0\n" 182 | "-p port number to listen on, default is 1984\n" 183 | "-d run as a deamon\n" 184 | "-t timeout for a http request, default is 120 seconds\n" 185 | "-h print this help and exit\n" 186 | "\n"; 187 | fprintf(stderr,"%s",help); 188 | } 189 | 190 | //当向进程发出SIGTERM/SIGHUP/SIGINT/SIGQUIT的时候,终止event的事件侦听循环 191 | void signal_handler(int sig) { 192 | switch (sig) { 193 | case SIGTERM: 194 | case SIGHUP: 195 | case SIGQUIT: 196 | case SIGINT: 197 | event_loopbreak(); //终止侦听event_dispatch()的事件侦听循环,执行之后的代码 198 | break; 199 | } 200 | } 201 | 202 | int main(int argc, char *argv[]) { 203 | //自定义信号处理函数 204 | signal(SIGHUP, signal_handler); 205 | signal(SIGTERM, signal_handler); 206 | signal(SIGINT, signal_handler); 207 | signal(SIGQUIT, signal_handler); 208 | 209 | //默认参数 210 | char *httpd_option_listen = "0.0.0.0"; 211 | int httpd_option_port = 7777; 212 | int httpd_option_daemon = 0; 213 | int httpd_option_timeout = 120; //in seconds 214 | 215 | //获取参数 216 | int c; 217 | while ((c = getopt(argc, argv, "l:p:dt:h")) != -1) { 218 | switch (c) { 219 | case 'l' : 220 | httpd_option_listen = optarg; 221 | break; 222 | case 'p' : 223 | httpd_option_port = atoi(optarg); 224 | break; 225 | case 'd' : 226 | httpd_option_daemon = 1; 227 | break; 228 | case 't' : 229 | httpd_option_timeout = atoi(optarg); 230 | break; 231 | case 'h' : 232 | default : 233 | show_help(); 234 | exit(EXIT_SUCCESS); 235 | } 236 | } 237 | 238 | //判断是否设置了-d,以daemon运行 239 | if (httpd_option_daemon) { 240 | pid_t pid; 241 | pid = fork(); 242 | if (pid < 0) { 243 | perror("fork failed"); 244 | exit(EXIT_FAILURE); 245 | } 246 | if (pid > 0) { 247 | //生成子进程成功,退出父进程 248 | exit(EXIT_SUCCESS); 249 | } 250 | } 251 | 252 | 253 | /* 使用libevent创建HTTP Server */ 254 | 255 | //初始化event API 256 | event_init(); 257 | 258 | //创建一个http server 259 | struct evhttp *httpd; 260 | 261 | httpd = evhttp_start(httpd_option_listen, httpd_option_port); 262 | 263 | evhttp_set_timeout(httpd, httpd_option_timeout); 264 | 265 | //也可以为特定的URI指定callback 266 | evhttp_set_cb(httpd, "/", httpd_handler, NULL); 267 | evhttp_set_cb(httpd, "/login", login_handler, NULL); 268 | 269 | //循环处理events 270 | event_dispatch(); 271 | 272 | evhttp_free(httpd); 273 | 274 | return 0; 275 | } 276 | -------------------------------------------------------------------------------- /https_server/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC=gcc 3 | CPPFLAGS= -I. -I./include 4 | CFLAGS=-Wall 5 | LIBS=-lpthread -levent -lm -lssl -lcrypto -levent_openssl 6 | 7 | #找到当前目录下所有的.c文件 8 | src = $(wildcard *.c) 9 | 10 | #将当前目录下所有的.c 转换成.o给obj 11 | obj = $(patsubst %.c, %.o, $(src)) 12 | 13 | 14 | server=server 15 | 16 | target=$(server) 17 | 18 | 19 | ALL:$(target) 20 | 21 | 22 | #生成所有的.o文件 23 | $(obj):%.o:%.c 24 | $(CC) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) 25 | 26 | 27 | #test_main程序 28 | $(server): https-server.o https-common.o cJSON.o 29 | $(CC) $^ -o $@ $(LIBS) 30 | 31 | 32 | 33 | 34 | 35 | #clean指令 36 | 37 | clean: 38 | -rm -rf $(obj) $(target) 39 | 40 | distclean: 41 | -rm -rf $(obj) $(target) 42 | 43 | #将clean目标 改成一个虚拟符号 44 | .PHONY: clean ALL distclean 45 | -------------------------------------------------------------------------------- /https_server/cJSON.c: -------------------------------------------------------------------------------- 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 | /* cJSON */ 24 | /* JSON parser in C. */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "cJSON.h" 34 | 35 | static const char *ep; 36 | 37 | const char *cJSON_GetErrorPtr(void) {return ep;} 38 | 39 | static int cJSON_strcasecmp(const char *s1,const char *s2) 40 | { 41 | if (!s1) return (s1==s2)?0:1;if (!s2) return 1; 42 | for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; 43 | return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); 44 | } 45 | 46 | static void *(*cJSON_malloc)(size_t sz) = malloc; 47 | static void (*cJSON_free)(void *ptr) = free; 48 | 49 | static char* cJSON_strdup(const char* str) 50 | { 51 | size_t len; 52 | char* copy; 53 | 54 | len = strlen(str) + 1; 55 | if (!(copy = (char*)cJSON_malloc(len))) return 0; 56 | memcpy(copy,str,len); 57 | return copy; 58 | } 59 | 60 | void cJSON_InitHooks(cJSON_Hooks* hooks) 61 | { 62 | if (!hooks) { /* Reset hooks */ 63 | cJSON_malloc = malloc; 64 | cJSON_free = free; 65 | return; 66 | } 67 | 68 | cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 69 | cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 70 | } 71 | 72 | /* Internal constructor. */ 73 | static cJSON *cJSON_New_Item(void) 74 | { 75 | cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 76 | if (node) memset(node,0,sizeof(cJSON)); 77 | return node; 78 | } 79 | 80 | /* Delete a cJSON structure. */ 81 | void cJSON_Delete(cJSON *c) 82 | { 83 | cJSON *next; 84 | while (c) 85 | { 86 | next=c->next; 87 | if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 88 | if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 89 | if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); 90 | cJSON_free(c); 91 | c=next; 92 | } 93 | } 94 | 95 | /* Parse the input text to generate a number, and populate the result into item. */ 96 | static const char *parse_number(cJSON *item,const char *num) 97 | { 98 | double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; 99 | 100 | if (*num=='-') sign=-1,num++; /* Has sign? */ 101 | if (*num=='0') num++; /* is zero */ 102 | if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ 103 | if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ 104 | if (*num=='e' || *num=='E') /* Exponent? */ 105 | { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ 106 | while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ 107 | } 108 | 109 | n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 110 | 111 | item->valuedouble=n; 112 | item->valueint=(int)n; 113 | item->type=cJSON_Number; 114 | return num; 115 | } 116 | 117 | static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } 118 | 119 | typedef struct {char *buffer; int length; int offset; } printbuffer; 120 | 121 | static char* ensure(printbuffer *p,int needed) 122 | { 123 | char *newbuffer;int newsize; 124 | if (!p || !p->buffer) return 0; 125 | needed+=p->offset; 126 | if (needed<=p->length) return p->buffer+p->offset; 127 | 128 | newsize=pow2gt(needed); 129 | newbuffer=(char*)cJSON_malloc(newsize); 130 | if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} 131 | if (newbuffer) memcpy(newbuffer,p->buffer,p->length); 132 | cJSON_free(p->buffer); 133 | p->length=newsize; 134 | p->buffer=newbuffer; 135 | return newbuffer+p->offset; 136 | } 137 | 138 | static int update(printbuffer *p) 139 | { 140 | char *str; 141 | if (!p || !p->buffer) return 0; 142 | str=p->buffer+p->offset; 143 | return p->offset+strlen(str); 144 | } 145 | 146 | /* Render the number nicely from the given item into a string. */ 147 | static char *print_number(cJSON *item,printbuffer *p) 148 | { 149 | char *str=0; 150 | double d=item->valuedouble; 151 | if (d==0) 152 | { 153 | if (p) str=ensure(p,2); 154 | else str=(char*)cJSON_malloc(2); /* special case for 0. */ 155 | if (str) strcpy(str,"0"); 156 | } 157 | else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 158 | { 159 | if (p) str=ensure(p,21); 160 | else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ 161 | if (str) sprintf(str,"%d",item->valueint); 162 | } 163 | else 164 | { 165 | if (p) str=ensure(p,64); 166 | else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ 167 | if (str) 168 | { 169 | if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); 170 | else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); 171 | else sprintf(str,"%f",d); 172 | } 173 | } 174 | return str; 175 | } 176 | 177 | static unsigned parse_hex4(const char *str) 178 | { 179 | unsigned h=0; 180 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 181 | h=h<<4;str++; 182 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 183 | h=h<<4;str++; 184 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 185 | h=h<<4;str++; 186 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 187 | return h; 188 | } 189 | 190 | /* Parse the input text into an unescaped cstring, and populate item. */ 191 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 192 | static const char *parse_string(cJSON *item,const char *str) 193 | { 194 | const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; 195 | if (*str!='\"') {ep=str;return 0;} /* not a string! */ 196 | 197 | while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ 198 | 199 | out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 200 | if (!out) return 0; 201 | 202 | ptr=str+1;ptr2=out; 203 | while (*ptr!='\"' && *ptr) 204 | { 205 | if (*ptr!='\\') *ptr2++=*ptr++; 206 | else 207 | { 208 | ptr++; 209 | switch (*ptr) 210 | { 211 | case 'b': *ptr2++='\b'; break; 212 | case 'f': *ptr2++='\f'; break; 213 | case 'n': *ptr2++='\n'; break; 214 | case 'r': *ptr2++='\r'; break; 215 | case 't': *ptr2++='\t'; break; 216 | case 'u': /* transcode utf16 to utf8. */ 217 | uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ 218 | 219 | if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ 220 | 221 | if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ 222 | { 223 | if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ 224 | uc2=parse_hex4(ptr+3);ptr+=6; 225 | if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ 226 | uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 227 | } 228 | 229 | len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; 230 | 231 | switch (len) { 232 | case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 233 | case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 234 | case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 235 | case 1: *--ptr2 =(uc | firstByteMark[len]); 236 | } 237 | ptr2+=len; 238 | break; 239 | default: *ptr2++=*ptr; break; 240 | } 241 | ptr++; 242 | } 243 | } 244 | *ptr2=0; 245 | if (*ptr=='\"') ptr++; 246 | item->valuestring=out; 247 | item->type=cJSON_String; 248 | return ptr; 249 | } 250 | 251 | /* Render the cstring provided to an escaped version that can be printed. */ 252 | static char *print_string_ptr(const char *str,printbuffer *p) 253 | { 254 | const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; 255 | 256 | for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; 257 | if (!flag) 258 | { 259 | len=ptr-str; 260 | if (p) out=ensure(p,len+3); 261 | else out=(char*)cJSON_malloc(len+3); 262 | if (!out) return 0; 263 | ptr2=out;*ptr2++='\"'; 264 | strcpy(ptr2,str); 265 | ptr2[len]='\"'; 266 | ptr2[len+1]=0; 267 | return out; 268 | } 269 | 270 | if (!str) 271 | { 272 | if (p) out=ensure(p,3); 273 | else out=(char*)cJSON_malloc(3); 274 | if (!out) return 0; 275 | strcpy(out,"\"\""); 276 | return out; 277 | } 278 | ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} 279 | 280 | if (p) out=ensure(p,len+3); 281 | else out=(char*)cJSON_malloc(len+3); 282 | if (!out) return 0; 283 | 284 | ptr2=out;ptr=str; 285 | *ptr2++='\"'; 286 | while (*ptr) 287 | { 288 | if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; 289 | else 290 | { 291 | *ptr2++='\\'; 292 | switch (token=*ptr++) 293 | { 294 | case '\\': *ptr2++='\\'; break; 295 | case '\"': *ptr2++='\"'; break; 296 | case '\b': *ptr2++='b'; break; 297 | case '\f': *ptr2++='f'; break; 298 | case '\n': *ptr2++='n'; break; 299 | case '\r': *ptr2++='r'; break; 300 | case '\t': *ptr2++='t'; break; 301 | default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ 302 | } 303 | } 304 | } 305 | *ptr2++='\"';*ptr2++=0; 306 | return out; 307 | } 308 | /* Invote print_string_ptr (which is useful) on an item. */ 309 | static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} 310 | 311 | /* Predeclare these prototypes. */ 312 | static const char *parse_value(cJSON *item,const char *value); 313 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); 314 | static const char *parse_array(cJSON *item,const char *value); 315 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); 316 | static const char *parse_object(cJSON *item,const char *value); 317 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); 318 | 319 | /* Utility to jump whitespace and cr/lf */ 320 | static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} 321 | 322 | /* Parse an object - create a new root, and populate. */ 323 | cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) 324 | { 325 | const char *end=0; 326 | cJSON *c=cJSON_New_Item(); 327 | ep=0; 328 | if (!c) return 0; /* memory fail */ 329 | 330 | end=parse_value(c,skip(value)); 331 | if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ 332 | 333 | /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 334 | if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} 335 | if (return_parse_end) *return_parse_end=end; 336 | return c; 337 | } 338 | /* Default options for cJSON_Parse */ 339 | cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} 340 | 341 | /* Render a cJSON item/entity/structure to text. */ 342 | char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} 343 | char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} 344 | 345 | char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) 346 | { 347 | printbuffer p; 348 | p.buffer=(char*)cJSON_malloc(prebuffer); 349 | p.length=prebuffer; 350 | p.offset=0; 351 | return print_value(item,0,fmt,&p); 352 | return p.buffer; 353 | } 354 | 355 | 356 | /* Parser core - when encountering text, process appropriately. */ 357 | static const char *parse_value(cJSON *item,const char *value) 358 | { 359 | if (!value) return 0; /* Fail on null. */ 360 | if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } 361 | if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 362 | if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } 363 | if (*value=='\"') { return parse_string(item,value); } 364 | if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } 365 | if (*value=='[') { return parse_array(item,value); } 366 | if (*value=='{') { return parse_object(item,value); } 367 | 368 | ep=value;return 0; /* failure. */ 369 | } 370 | 371 | /* Render a value to text. */ 372 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) 373 | { 374 | char *out=0; 375 | if (!item) return 0; 376 | if (p) 377 | { 378 | switch ((item->type)&255) 379 | { 380 | case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} 381 | case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} 382 | case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} 383 | case cJSON_Number: out=print_number(item,p);break; 384 | case cJSON_String: out=print_string(item,p);break; 385 | case cJSON_Array: out=print_array(item,depth,fmt,p);break; 386 | case cJSON_Object: out=print_object(item,depth,fmt,p);break; 387 | } 388 | } 389 | else 390 | { 391 | switch ((item->type)&255) 392 | { 393 | case cJSON_NULL: out=cJSON_strdup("null"); break; 394 | case cJSON_False: out=cJSON_strdup("false");break; 395 | case cJSON_True: out=cJSON_strdup("true"); break; 396 | case cJSON_Number: out=print_number(item,0);break; 397 | case cJSON_String: out=print_string(item,0);break; 398 | case cJSON_Array: out=print_array(item,depth,fmt,0);break; 399 | case cJSON_Object: out=print_object(item,depth,fmt,0);break; 400 | } 401 | } 402 | return out; 403 | } 404 | 405 | /* Build an array from input text. */ 406 | static const char *parse_array(cJSON *item,const char *value) 407 | { 408 | cJSON *child; 409 | if (*value!='[') {ep=value;return 0;} /* not an array! */ 410 | 411 | item->type=cJSON_Array; 412 | value=skip(value+1); 413 | if (*value==']') return value+1; /* empty array. */ 414 | 415 | item->child=child=cJSON_New_Item(); 416 | if (!item->child) return 0; /* memory fail */ 417 | value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 418 | if (!value) return 0; 419 | 420 | while (*value==',') 421 | { 422 | cJSON *new_item; 423 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 424 | child->next=new_item;new_item->prev=child;child=new_item; 425 | value=skip(parse_value(child,skip(value+1))); 426 | if (!value) return 0; /* memory fail */ 427 | } 428 | 429 | if (*value==']') return value+1; /* end of array */ 430 | ep=value;return 0; /* malformed. */ 431 | } 432 | 433 | /* Render an array to text */ 434 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) 435 | { 436 | char **entries; 437 | char *out=0,*ptr,*ret;int len=5; 438 | cJSON *child=item->child; 439 | int numentries=0,i=0,fail=0; 440 | size_t tmplen=0; 441 | 442 | /* How many entries in the array? */ 443 | while (child) numentries++,child=child->next; 444 | /* Explicitly handle numentries==0 */ 445 | if (!numentries) 446 | { 447 | if (p) out=ensure(p,3); 448 | else out=(char*)cJSON_malloc(3); 449 | if (out) strcpy(out,"[]"); 450 | return out; 451 | } 452 | 453 | if (p) 454 | { 455 | /* Compose the output array. */ 456 | i=p->offset; 457 | ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; 458 | child=item->child; 459 | while (child && !fail) 460 | { 461 | print_value(child,depth+1,fmt,p); 462 | p->offset=update(p); 463 | if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} 464 | child=child->next; 465 | } 466 | ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; 467 | out=(p->buffer)+i; 468 | } 469 | else 470 | { 471 | /* Allocate an array to hold the values for each */ 472 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 473 | if (!entries) return 0; 474 | memset(entries,0,numentries*sizeof(char*)); 475 | /* Retrieve all the results: */ 476 | child=item->child; 477 | while (child && !fail) 478 | { 479 | ret=print_value(child,depth+1,fmt,0); 480 | entries[i++]=ret; 481 | if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 482 | child=child->next; 483 | } 484 | 485 | /* If we didn't fail, try to malloc the output string */ 486 | if (!fail) out=(char*)cJSON_malloc(len); 487 | /* If that fails, we fail. */ 488 | if (!out) fail=1; 489 | 490 | /* Handle failure. */ 491 | if (fail) 492 | { 493 | for (i=0;itype=cJSON_Object; 520 | value=skip(value+1); 521 | if (*value=='}') return value+1; /* empty array. */ 522 | 523 | item->child=child=cJSON_New_Item(); 524 | if (!item->child) return 0; 525 | value=skip(parse_string(child,skip(value))); 526 | if (!value) return 0; 527 | child->string=child->valuestring;child->valuestring=0; 528 | if (*value!=':') {ep=value;return 0;} /* fail! */ 529 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 530 | if (!value) return 0; 531 | 532 | while (*value==',') 533 | { 534 | cJSON *new_item; 535 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 536 | child->next=new_item;new_item->prev=child;child=new_item; 537 | value=skip(parse_string(child,skip(value+1))); 538 | if (!value) return 0; 539 | child->string=child->valuestring;child->valuestring=0; 540 | if (*value!=':') {ep=value;return 0;} /* fail! */ 541 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 542 | if (!value) return 0; 543 | } 544 | 545 | if (*value=='}') return value+1; /* end of array */ 546 | ep=value;return 0; /* malformed. */ 547 | } 548 | 549 | /* Render an object to text. */ 550 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) 551 | { 552 | char **entries=0,**names=0; 553 | char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 554 | cJSON *child=item->child; 555 | int numentries=0,fail=0; 556 | size_t tmplen=0; 557 | /* Count the number of entries. */ 558 | while (child) numentries++,child=child->next; 559 | /* Explicitly handle empty object case */ 560 | if (!numentries) 561 | { 562 | if (p) out=ensure(p,fmt?depth+4:3); 563 | else out=(char*)cJSON_malloc(fmt?depth+4:3); 564 | if (!out) return 0; 565 | ptr=out;*ptr++='{'; 566 | if (fmt) {*ptr++='\n';for (i=0;ioffset; 574 | len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; 575 | *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; 576 | child=item->child;depth++; 577 | while (child) 578 | { 579 | if (fmt) 580 | { 581 | ptr=ensure(p,depth); if (!ptr) return 0; 582 | for (j=0;joffset+=depth; 584 | } 585 | print_string_ptr(child->string,p); 586 | p->offset=update(p); 587 | 588 | len=fmt?2:1; 589 | ptr=ensure(p,len); if (!ptr) return 0; 590 | *ptr++=':';if (fmt) *ptr++='\t'; 591 | p->offset+=len; 592 | 593 | print_value(child,depth,fmt,p); 594 | p->offset=update(p); 595 | 596 | len=(fmt?1:0)+(child->next?1:0); 597 | ptr=ensure(p,len+1); if (!ptr) return 0; 598 | if (child->next) *ptr++=','; 599 | if (fmt) *ptr++='\n';*ptr=0; 600 | p->offset+=len; 601 | child=child->next; 602 | } 603 | ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; 604 | if (fmt) for (i=0;ibuffer)+i; 607 | } 608 | else 609 | { 610 | /* Allocate space for the names and the objects */ 611 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 612 | if (!entries) return 0; 613 | names=(char**)cJSON_malloc(numentries*sizeof(char*)); 614 | if (!names) {cJSON_free(entries);return 0;} 615 | memset(entries,0,sizeof(char*)*numentries); 616 | memset(names,0,sizeof(char*)*numentries); 617 | 618 | /* Collect all the results into our arrays: */ 619 | child=item->child;depth++;if (fmt) len+=depth; 620 | while (child) 621 | { 622 | names[i]=str=print_string_ptr(child->string,0); 623 | entries[i++]=ret=print_value(child,depth,fmt,0); 624 | if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 625 | child=child->next; 626 | } 627 | 628 | /* Try to allocate the output string */ 629 | if (!fail) out=(char*)cJSON_malloc(len); 630 | if (!out) fail=1; 631 | 632 | /* Handle failure */ 633 | if (fail) 634 | { 635 | for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} 662 | cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} 663 | cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} 664 | 665 | /* Utility for array list handling. */ 666 | static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} 667 | /* Utility for handling references. */ 668 | static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 669 | 670 | /* Add item to array/object. */ 671 | void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} 672 | void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} 673 | void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} 674 | void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} 675 | void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} 676 | 677 | cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; 678 | if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} 679 | void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} 680 | cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} 681 | void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} 682 | 683 | /* Replace array/object items with new ones. */ 684 | void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} 685 | newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} 686 | void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; 687 | newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; 688 | if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} 689 | void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} 690 | 691 | /* Create basic types: */ 692 | cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} 693 | cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} 694 | cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} 695 | cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} 696 | cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} 697 | cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} 698 | cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} 699 | cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} 700 | 701 | /* Create Arrays: */ 702 | cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 703 | cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 704 | cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 705 | cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 706 | 707 | /* Duplication */ 708 | cJSON *cJSON_Duplicate(cJSON *item,int recurse) 709 | { 710 | cJSON *newitem,*cptr,*nptr=0,*newchild; 711 | /* Bail on bad ptr */ 712 | if (!item) return 0; 713 | /* Create new item */ 714 | newitem=cJSON_New_Item(); 715 | if (!newitem) return 0; 716 | /* Copy over all vars */ 717 | newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; 718 | if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} 719 | if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} 720 | /* If non-recursive, then we're done! */ 721 | if (!recurse) return newitem; 722 | /* Walk the ->next chain for the child. */ 723 | cptr=item->child; 724 | while (cptr) 725 | { 726 | newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ 727 | if (!newchild) {cJSON_Delete(newitem);return 0;} 728 | if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 729 | else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ 730 | cptr=cptr->next; 731 | } 732 | return newitem; 733 | } 734 | 735 | void cJSON_Minify(char *json) 736 | { 737 | char *into=json; 738 | while (*json) 739 | { 740 | if (*json==' ') json++; 741 | else if (*json=='\t') json++; /* Whitespace characters. */ 742 | else if (*json=='\r') json++; 743 | else if (*json=='\n') json++; 744 | else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ 745 | else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ 746 | else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ 747 | else *into++=*json++; /* All other characters. */ 748 | } 749 | *into=0; /* and null-terminate. */ 750 | } 751 | -------------------------------------------------------------------------------- /https_server/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 | #define cJSON_StringIsConst 512 42 | 43 | /* The cJSON structure: */ 44 | typedef struct cJSON { 45 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 46 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 47 | 48 | int type; /* The type of the item, as above. */ 49 | 50 | char *valuestring; /* The item's string, if type==cJSON_String */ 51 | int valueint; /* 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 | /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ 73 | extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); 74 | /* Delete a cJSON entity and all subentities. */ 75 | extern void cJSON_Delete(cJSON *c); 76 | 77 | /* Returns the number of items in an array (or object). */ 78 | extern int cJSON_GetArraySize(cJSON *array); 79 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 80 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 81 | /* Get item "string" from object. Case insensitive. */ 82 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 83 | 84 | /* 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. */ 85 | extern const char *cJSON_GetErrorPtr(void); 86 | 87 | /* These calls create a cJSON item of the appropriate type. */ 88 | extern cJSON *cJSON_CreateNull(void); 89 | extern cJSON *cJSON_CreateTrue(void); 90 | extern cJSON *cJSON_CreateFalse(void); 91 | extern cJSON *cJSON_CreateBool(int b); 92 | extern cJSON *cJSON_CreateNumber(double num); 93 | extern cJSON *cJSON_CreateString(const char *string); 94 | extern cJSON *cJSON_CreateArray(void); 95 | extern cJSON *cJSON_CreateObject(void); 96 | 97 | /* These utilities create an Array of count items. */ 98 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 99 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 100 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 101 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 102 | 103 | /* Append item to the specified array/object. */ 104 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 105 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 106 | extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ 107 | /* 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. */ 108 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 109 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 110 | 111 | /* Remove/Detatch items from Arrays/Objects. */ 112 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 113 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 114 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 115 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 116 | 117 | /* Update array items. */ 118 | extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ 119 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 120 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 121 | 122 | /* Duplicate a cJSON item */ 123 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 124 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 125 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 126 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 127 | 128 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 129 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 130 | 131 | extern void cJSON_Minify(char *json); 132 | 133 | /* Macros for creating things quickly. */ 134 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 135 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 136 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 137 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 138 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 139 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 140 | 141 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 142 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 143 | #define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 144 | 145 | #ifdef __cplusplus 146 | } 147 | #endif 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /https_server/https-common.c: -------------------------------------------------------------------------------- 1 | 2 | /* (c) Oblong Industries */ 3 | 4 | #include 5 | 6 | #include "https-common.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | 14 | /* 这个是调用openSSL提供的打印log接口 */ 15 | void die_most_horribly_from_openssl_error (const char *func) 16 | { 17 | fprintf (stderr, "%s failed:\n", func); 18 | 19 | /* This is the OpenSSL function that prints the contents of the 20 | * error stack to the specified file handle. */ 21 | ERR_print_errors_fp (stderr); 22 | 23 | exit (EXIT_FAILURE); 24 | } 25 | 26 | void error_exit (const char *fmt, ...) 27 | { va_list ap; 28 | 29 | va_start (ap, fmt); 30 | vfprintf (stderr, fmt, ap); 31 | va_end (ap); 32 | 33 | exit (EXIT_FAILURE); 34 | } 35 | 36 | /* OpenSSL has a habit of using uninitialized memory. (They turn up their 37 | * nose at tools like valgrind.) To avoid spurious valgrind errors (as well 38 | * as to allay any concerns that the uninitialized memory is actually 39 | * affecting behavior), let's install a custom malloc function which is 40 | * actually calloc. 41 | */ 42 | static void *my_zeroing_malloc (size_t howmuch) 43 | { 44 | return calloc (1, howmuch); 45 | } 46 | 47 | void common_setup (void) 48 | { 49 | signal (SIGPIPE, SIG_IGN); 50 | 51 | CRYPTO_set_mem_functions (my_zeroing_malloc, realloc, free); 52 | SSL_library_init (); 53 | SSL_load_error_strings (); 54 | OpenSSL_add_all_algorithms (); 55 | 56 | printf ("Using OpenSSL version \"%s\"\nand libevent version \"%s\"\n", 57 | SSLeay_version (SSLEAY_VERSION), 58 | event_get_version ()); 59 | } 60 | -------------------------------------------------------------------------------- /https_server/https-common.h: -------------------------------------------------------------------------------- 1 | 2 | /* (c) Oblong Industries */ 3 | 4 | #ifndef COMMON_MAN 5 | #define COMMON_MAN 6 | 7 | /** 8 | * Rather than using the standard https port of 443, use this one. 9 | */ 10 | #define COMMON_HTTPS_PORT 8080 11 | 12 | /** 13 | * This is the string the client tells the server in the POST request. 14 | */ 15 | #define COMMON_PASSCODE "R23" 16 | 17 | /** 18 | * If an OpenSSL function returns a return value indicating failure 19 | * (for non-pointery functions, generally 1 means success, and non-1 20 | * means failure), then usually it ought to have left one or more 21 | * entries in the OpenSSL "error stack", which is a bit of thread-local 22 | * state containing error information. 23 | * 24 | * This function is a simple way to handle OpenSSL errors (something 25 | * better may be needed in a real application), which prints the 26 | * name of the function which failed (which you must supply as an 27 | * argument), prints the OpenSSL error stack (which hopefully says 28 | * something meaningful) and exits. 29 | */ 30 | void die_most_horribly_from_openssl_error (const char *func); 31 | 32 | void error_exit (const char *fmt, ...); 33 | 34 | #define error_report printf 35 | #define info_report printf 36 | 37 | /** 38 | * Calls some OpenSSL setup functions, which both the client and 39 | * server need to do. 40 | */ 41 | void common_setup (void); 42 | 43 | #endif /* COMMON_MAN */ 44 | -------------------------------------------------------------------------------- /https_server/https-server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file https-server.c 3 | * @brief 4 | * @author liu_danbing 5 | * @version 1.0 6 | * @date 2016-10-26 7 | */ 8 | 9 | #include "https-common.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | 38 | #define MYHTTPD_SIGNATURE "MoCarHttpd v0.1" 39 | 40 | 41 | #ifdef EVENT__HAVE_NETINET_IN_H 42 | #include 43 | # ifdef _XOPEN_SOURCE_EXTENDED 44 | # include 45 | # endif 46 | #endif 47 | 48 | unsigned short serverPort = COMMON_HTTPS_PORT; 49 | 50 | /* Instead of casting between these types, create a union with all of them, 51 | * to avoid -Wstrict-aliasing warnings. */ 52 | typedef union 53 | { 54 | struct sockaddr_storage ss; 55 | struct sockaddr sa; 56 | struct sockaddr_in in; 57 | struct sockaddr_in6 i6; 58 | } sock_hop; 59 | 60 | 61 | /* This callback gets invoked when we get any http request that doesn't match 62 | * any other callback. Like any evhttp server callback, it has a simple job: 63 | * it must eventually call evhttp_send_error() or evhttp_send_reply(). 64 | */ 65 | static void 66 | login_cb (struct evhttp_request *req, void *arg) 67 | { 68 | struct evbuffer *evb = NULL; 69 | const char *uri = evhttp_request_get_uri (req); 70 | struct evhttp_uri *decoded = NULL; 71 | 72 | /* 判断 req 是否是GET 请求 */ 73 | if (evhttp_request_get_command (req) == EVHTTP_REQ_GET) 74 | { 75 | struct evbuffer *buf = evbuffer_new(); 76 | if (buf == NULL) return; 77 | evbuffer_add_printf(buf, "Requested: %s\n", uri); 78 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 79 | return; 80 | } 81 | 82 | /* 这里只处理Post请求, Get请求,就直接return 200 OK */ 83 | if (evhttp_request_get_command (req) != EVHTTP_REQ_POST) 84 | { 85 | evhttp_send_reply (req, 200, "OK", NULL); 86 | return; 87 | } 88 | 89 | printf ("Got a POST request for <%s>\n", uri); 90 | 91 | //判断此URI是否合法 92 | decoded = evhttp_uri_parse (uri); 93 | if (! decoded) 94 | { 95 | printf ("It's not a good URI. Sending BADREQUEST\n"); 96 | evhttp_send_error (req, HTTP_BADREQUEST, 0); 97 | return; 98 | } 99 | 100 | /* Decode the payload */ 101 | struct evbuffer *buf = evhttp_request_get_input_buffer (req); 102 | evbuffer_add (buf, "", 1); /* NUL-terminate the buffer */ 103 | char *payload = (char *) evbuffer_pullup (buf, -1); 104 | int post_data_len = evbuffer_get_length(buf); 105 | char request_data_buf[4096] = {0}; 106 | memcpy(request_data_buf, payload, post_data_len); 107 | 108 | printf("[post_data][%d]=\n %s\n", post_data_len, payload); 109 | 110 | 111 | /* 112 | 具体的:可以根据Post的参数执行相应操作,然后将结果输出 113 | ... 114 | */ 115 | //unpack json 116 | cJSON* root = cJSON_Parse(request_data_buf); 117 | cJSON* username = cJSON_GetObjectItem(root, "username"); 118 | cJSON* password = cJSON_GetObjectItem(root, "password"); 119 | cJSON* driver = cJSON_GetObjectItem(root, "driver"); 120 | 121 | printf("username = %s\n", username->valuestring); 122 | printf("password = %s\n", password->valuestring); 123 | printf("driver = %s\n", driver->valuestring); 124 | 125 | cJSON_Delete(root); 126 | 127 | 128 | 129 | //packet json 130 | root = cJSON_CreateObject(); 131 | 132 | cJSON_AddStringToObject(root, "result", "ok"); 133 | //cJSON_AddStringToObject(root, "sessionid", "xxxxxxxx"); 134 | 135 | char *response_data = cJSON_Print(root); 136 | cJSON_Delete(root); 137 | 138 | 139 | 140 | 141 | /* This holds the content we're sending. */ 142 | 143 | //HTTP header 144 | evhttp_add_header(evhttp_request_get_output_headers(req), "Server", MYHTTPD_SIGNATURE); 145 | evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/plain; charset=UTF-8"); 146 | evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); 147 | 148 | evb = evbuffer_new (); 149 | evbuffer_add_printf(evb, "%s", response_data); 150 | //将封装好的evbuffer 发送给客户端 151 | evhttp_send_reply(req, HTTP_OK, "OK", evb); 152 | 153 | if (decoded) 154 | evhttp_uri_free (decoded); 155 | if (evb) 156 | evbuffer_free (evb); 157 | 158 | 159 | printf("[response]:\n"); 160 | printf("%s\n", response_data); 161 | 162 | free(response_data); 163 | } 164 | 165 | /** 166 | * This callback is responsible for creating a new SSL connection 167 | * and wrapping it in an OpenSSL bufferevent. This is the way 168 | * we implement an https server instead of a plain old http server. 169 | */ 170 | static struct bufferevent* bevcb (struct event_base *base, void *arg) 171 | { 172 | struct bufferevent* r; 173 | SSL_CTX *ctx = (SSL_CTX *) arg; 174 | 175 | r = bufferevent_openssl_socket_new (base, 176 | -1, 177 | SSL_new (ctx), 178 | BUFFEREVENT_SSL_ACCEPTING, 179 | BEV_OPT_CLOSE_ON_FREE); 180 | return r; 181 | } 182 | 183 | static void server_setup_certs (SSL_CTX *ctx, 184 | const char *certificate_chain, 185 | const char *private_key) 186 | { 187 | info_report ("Loading certificate chain from '%s'\n" 188 | "and private key from '%s'\n", 189 | certificate_chain, private_key); 190 | 191 | if (1 != SSL_CTX_use_certificate_chain_file (ctx, certificate_chain)) 192 | die_most_horribly_from_openssl_error ("SSL_CTX_use_certificate_chain_file"); 193 | 194 | if (1 != SSL_CTX_use_PrivateKey_file (ctx, private_key, SSL_FILETYPE_PEM)) 195 | die_most_horribly_from_openssl_error ("SSL_CTX_use_PrivateKey_file"); 196 | 197 | if (1 != SSL_CTX_check_private_key (ctx)) 198 | die_most_horribly_from_openssl_error ("SSL_CTX_check_private_key"); 199 | } 200 | 201 | static int serve_some_http (void) 202 | { 203 | struct event_base *base; 204 | struct evhttp *http; 205 | struct evhttp_bound_socket *handle; 206 | 207 | 208 | base = event_base_new (); 209 | if (! base) 210 | { 211 | fprintf (stderr, "Couldn't create an event_base: exiting\n"); 212 | return 1; 213 | } 214 | 215 | /* 创建一个 evhttp 句柄,去处理用户端的requests请求 */ 216 | http = evhttp_new (base); 217 | if (! http) 218 | { fprintf (stderr, "couldn't create evhttp. Exiting.\n"); 219 | return 1; 220 | } 221 | 222 | /* 创建SSL上下文环境 ,可以理解为 SSL句柄 */ 223 | SSL_CTX *ctx = SSL_CTX_new (SSLv23_server_method ()); 224 | SSL_CTX_set_options (ctx, 225 | SSL_OP_SINGLE_DH_USE | 226 | SSL_OP_SINGLE_ECDH_USE | 227 | SSL_OP_NO_SSLv2); 228 | 229 | /* Cheesily pick an elliptic curve to use with elliptic curve ciphersuites. 230 | * We just hardcode a single curve which is reasonably decent. 231 | * See http://www.mail-archive.com/openssl-dev@openssl.org/msg30957.html */ 232 | EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); 233 | if (! ecdh) 234 | die_most_horribly_from_openssl_error ("EC_KEY_new_by_curve_name"); 235 | if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) 236 | die_most_horribly_from_openssl_error ("SSL_CTX_set_tmp_ecdh"); 237 | 238 | /* 选择服务器证书 和 服务器私钥. */ 239 | const char *certificate_chain = "server-certificate-chain.pem"; 240 | const char *private_key = "server-private-key.pem"; 241 | /* 设置服务器证书 和 服务器私钥 到 242 | OPENSSL ctx上下文句柄中 */ 243 | server_setup_certs (ctx, certificate_chain, private_key); 244 | 245 | /* 246 | 使我们创建好的evhttp句柄 支持 SSL加密 247 | 实际上,加密的动作和解密的动作都已经帮 248 | 我们自动完成,我们拿到的数据就已经解密之后的 249 | */ 250 | evhttp_set_bevcb (http, bevcb, ctx); 251 | 252 | /* 设置http回调函数 */ 253 | //默认回调 254 | //专属uri路径回调 255 | evhttp_set_cb(http, "/login", login_cb, NULL); 256 | 257 | /* 设置监听IP和端口 */ 258 | handle = evhttp_bind_socket_with_handle (http, "0.0.0.0", serverPort); 259 | if (! handle) 260 | { 261 | fprintf (stderr, "couldn't bind to port %d. Exiting.\n",(int) serverPort); 262 | return 1; 263 | } 264 | 265 | { 266 | /* 打印收到的客户端链接信息 */ 267 | sock_hop ss; 268 | evutil_socket_t fd; 269 | ev_socklen_t socklen = sizeof (ss); 270 | char addrbuf[128]; 271 | void *inaddr; 272 | const char *addr; 273 | int got_port = -1; 274 | 275 | fd = evhttp_bound_socket_get_fd (handle); 276 | memset (&ss, 0, sizeof(ss)); 277 | 278 | if (getsockname (fd, &ss.sa, &socklen)) 279 | { 280 | perror ("getsockname() failed"); 281 | return 1; 282 | } 283 | if (ss.ss.ss_family == AF_INET) 284 | { 285 | got_port = ntohs (ss.in.sin_port); 286 | inaddr = &ss.in.sin_addr; 287 | } 288 | else if (ss.ss.ss_family == AF_INET6) 289 | { 290 | got_port = ntohs (ss.i6.sin6_port); 291 | inaddr = &ss.i6.sin6_addr; 292 | } 293 | else 294 | { 295 | fprintf (stderr, "Weird address family %d\n", ss.ss.ss_family); 296 | return 1; 297 | } 298 | addr = evutil_inet_ntop (ss.ss.ss_family, inaddr, addrbuf, 299 | sizeof (addrbuf)); 300 | if (addr) 301 | printf ("Listening on %s:%d\n", addr, got_port); 302 | else 303 | { 304 | fprintf (stderr, "evutil_inet_ntop failed\n"); 305 | return 1; 306 | } 307 | } 308 | 309 | /* 开始阻塞监听 (永久执行) */ 310 | event_base_dispatch (base); 311 | 312 | 313 | return 0; 314 | } 315 | 316 | int main (int argc, char **argv) 317 | { 318 | /*OpenSSL 初始化 */ 319 | common_setup (); 320 | 321 | if (argc > 1) { 322 | char *end_ptr; 323 | long lp = strtol(argv[1], &end_ptr, 0); 324 | if (*end_ptr) { 325 | fprintf(stderr, "Invalid integer\n"); 326 | return -1; 327 | } 328 | if (lp <= 0) { 329 | fprintf(stderr, "Port must be positive\n"); 330 | return -1; 331 | } 332 | if (lp >= USHRT_MAX) { 333 | fprintf(stderr, "Port must fit 16-bit range\n"); 334 | return -1; 335 | } 336 | 337 | serverPort = (unsigned short)lp; 338 | } 339 | 340 | /* now run http server (never returns) */ 341 | return serve_some_http (); 342 | } 343 | -------------------------------------------------------------------------------- /https_server/server-certificate-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDVDCCAj6gAwIBAgIBAzALBgkqhkiG9w0BAQUwgYcxCzAJBgNVBAYTAlVTMRMw 3 | EQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtMb3MgQW5nZWxlczEaMBgGA1UE 4 | ChMRT2Jsb25nIEluZHVzdHJpZXMxDzANBgNVBAsTBlBsYXNtYTEgMB4GA1UEAxMX 5 | Y2hpdmVzLmxhOTIzLm9ibG9uZy5uZXQwHhcNMTIwNjA1MDIzMjE2WhcNMTcwNjA1 6 | MDIzMjE2WjBxMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFDASBgNVBAcTC0xv 7 | cyBBbmdlbGVzMRowGAYDVQQKExFPYmxvbmcgSW5kdXN0cmllczEPMA0GA1UECxMG 8 | UGxhc21hMRIwEAYDVQQDEwlsb2NhbGhvc3QwgZwwCwYJKoZIhvcNAQEBA4GMADCB 9 | iAKBgL68De74WCE0OcoCze9ekkcNsK864Ll2e0HzBDjIade6Zefmn3iesOOPPW3O 10 | t+p6DOfFJqeKJ3VwBQBRAf5gIeOwzNjBvyTOZm+6G7d243GCvozT62GvcQTxCXHq 11 | CkxVjQY5xd7kvwTKiB2ydseVtrciwjyRKPderenPRNIVcpeLAgMBAAGjazBpMB8G 12 | A1UdIwQYMBaAFDcoIJmKB1ym9TvFnuTo3zyVZkTkMAwGA1UdEwEB/wQCMAAwDwYD 13 | VR0PAQH/BAUDAwe4ADAnBgNVHSUEIDAeBggrBgEFBQcDBAYIKwYBBQUHAwIGCCsG 14 | AQUFBwMBMAsGCSqGSIb3DQEBBQOCAQEAZ8f9tHOaq9tIo76rBAVb3I+2lYufjEcx 15 | Vj36+O2Szmx6WBRCpvnGLwVyx7OuFqCGBaoFBRlkSXMOTCQHRE58l7XZ0F4t86hm 16 | Lf06qtyHUDIwNAVXLXkk+5HC2L1nnFQXhpqlZkpqQfIb4o5X3xtxvBquZjXygncO 17 | pCo7O/U5afaxUET2lQ55eLvONt0jWITdoBjuOymahJzPq17elDRPvQg58x7WjH/j 18 | bTrP1MHdKWKPSZ/ByOOnuHEm0RFc/jDqGiju10roIhZ7LwCSg0YP+kQL0lcs9EiY 19 | 13nVCIgoILzFG/rNg7+IQ3zlp6rMtCM8bLZ+r2joN1ABuIOQPS/4Ow== 20 | -----END CERTIFICATE----- 21 | -----BEGIN CERTIFICATE----- 22 | MIID6DCCAtKgAwIBAgIBATALBgkqhkiG9w0BAQUwgYcxCzAJBgNVBAYTAlVTMRMw 23 | EQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtMb3MgQW5nZWxlczEaMBgGA1UE 24 | ChMRT2Jsb25nIEluZHVzdHJpZXMxDzANBgNVBAsTBlBsYXNtYTEgMB4GA1UEAxMX 25 | Y2hpdmVzLmxhOTIzLm9ibG9uZy5uZXQwHhcNMTIwNTI1MDI1NzMzWhcNMzIwNTI1 26 | MDI1NzMzWjCBhzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDAS 27 | BgNVBAcTC0xvcyBBbmdlbGVzMRowGAYDVQQKExFPYmxvbmcgSW5kdXN0cmllczEP 28 | MA0GA1UECxMGUGxhc21hMSAwHgYDVQQDExdjaGl2ZXMubGE5MjMub2Jsb25nLm5l 29 | dDCCAR8wCwYJKoZIhvcNAQEBA4IBDgAwggEJAoIBALfDzI+LZTJ1f/b0hD/q6cvs 30 | JYV1SM2fudV25prref0XoYDCefK7HchyTyb/HleV2+icAvAODfMlKZOo+yOR/839 31 | GenV9aJFx6G+UVuzkymEFOieWV8013vPxE83oEkzhaY/fLYDebThM69F2kMp3xng 32 | ZTyVOVHq8I6Ca3us0LoAS3z8kHQAYnSkvh5BYYqUXS3Ch9/ljSjuAWGaSZ4x7LQB 33 | 2VRj5Q6LySvZxFmgPbs19tE3l2bSvHCJtTI9VTpZxXy182EGhk4spz2UMwaaPs0F 34 | duV+GVFNgRoct6iz76v6YDo+zip/QuJN7iZnzspfn+QkoyDztyeY4zkm7ja4AJMC 35 | AwEAAaNkMGIwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0GA1Ud 36 | DgQWBBQ3KCCZigdcpvU7xZ7k6N88lWZE5DAfBgNVHSMEGDAWgBQ3KCCZigdcpvU7 37 | xZ7k6N88lWZE5DALBgkqhkiG9w0BAQUDggEBABaDKcP7bsRCJk1QKykeDV/poKGZ 38 | gAcObl5379Hazim5Rt9B3OGzA/pqP/yVdgm9Y5GapmiAXgNdWYmLUsx4Ie4gRmgd 39 | HtV4PAyyk5ula0Q17JASIDCRkkSOFJDxMJgyXNW1mGnc7W3ujTKIWa+NeNqy1wc+ 40 | BzWiL3xsPSZ+kqeRLzp9ZQQNKUqevA9J/rqVpvw1+K3wH4YBkDSoc+iE+dMC0M4I 41 | i7iz0f1ylM+xTipTzgz1RWIBUt9OLaIXStvG2NrmRkk4cgFjP2sgE7hLFrT+tnYm 42 | I+HNJhhhspB6uEVHXWrXJ7WQ2UEPHGdhJBBm0zO87cCE/8IGfxB3WP4uHks= 43 | -----END CERTIFICATE----- 44 | -------------------------------------------------------------------------------- /https_server/server-private-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQC+vA3u+FghNDnKAs3vXpJHDbCvOuC5dntB8wQ4yGnXumXn5p94 3 | nrDjjz1tzrfqegznxSaniid1cAUAUQH+YCHjsMzYwb8kzmZvuhu3duNxgr6M0+th 4 | r3EE8Qlx6gpMVY0GOcXe5L8EyogdsnbHlba3IsI8kSj3Xq3pz0TSFXKXiwIDAQAB 5 | AoGAXdUEAck5CfS4bVId36Gl0sDAaCROA89u6c3VCN5He7KeiYxibaOcIAcK0Gd/ 6 | ASJUEP1je86yhMq8GyC/G1ZNtO1O6Xo2uYywROzr5MNahA5nnyiXlk7RsNYfkUMu 7 | 8lRAAHynI1eB7iPIWX0APIh61cSSfh3WVIrMP/tT62MKeAkCQQDStkv5bbRpMuSP 8 | kGOBSC2g4YynkDwuaK2gVVJIab5pJ3X9dZ8pcHyIx4s0k7Z96qurNGUZsgopEv7a 9 | 1L3JIpJ3AkEA57qQfVRKnNDhuo6eIoGRQpnu6uIXS7javjAVOUaAITZaY02Gh4Cz 10 | hHAm1/qKrPFepTNBH9EsAeZ0ZSZVPcZ0jQJBAJRRk2rwaMR/+ViAxznyR4PuH+a2 11 | 5VW5gzXPuQqVvF0iVLBjgfRWZKKW6wrISvWZINtzFxMeOn6tC02X4DtbJYMCQHnp 12 | lkDJiuOLpWZPx/RhdDm04JRkVFs7KqHqjA/w/lH61Xzu+XrqhAeGNXllT3YDGocR 13 | Ow7xLhTl2JCqpSf187UCQHY3feozIwgOf25UKbEpZF9cikTyGx4AYQx3zijLgd48 14 | xyLarqimKw8nNeKWQImLsalGiaw2h62H1Ajg6RGIWU0= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /login/cJSON.cpp: -------------------------------------------------------------------------------- 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 | /* cJSON */ 24 | /* JSON parser in C. */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "cJSON.h" 34 | 35 | static const char *ep; 36 | 37 | const char *cJSON_GetErrorPtr(void) {return ep;} 38 | 39 | static int cJSON_strcasecmp(const char *s1,const char *s2) 40 | { 41 | if (!s1) return (s1==s2)?0:1;if (!s2) return 1; 42 | for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; 43 | return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); 44 | } 45 | 46 | static void *(*cJSON_malloc)(size_t sz) = malloc; 47 | static void (*cJSON_free)(void *ptr) = free; 48 | 49 | static char* cJSON_strdup(const char* str) 50 | { 51 | size_t len; 52 | char* copy; 53 | 54 | len = strlen(str) + 1; 55 | if (!(copy = (char*)cJSON_malloc(len))) return 0; 56 | memcpy(copy,str,len); 57 | return copy; 58 | } 59 | 60 | void cJSON_InitHooks(cJSON_Hooks* hooks) 61 | { 62 | if (!hooks) { /* Reset hooks */ 63 | cJSON_malloc = malloc; 64 | cJSON_free = free; 65 | return; 66 | } 67 | 68 | cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 69 | cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 70 | } 71 | 72 | /* Internal constructor. */ 73 | static cJSON *cJSON_New_Item(void) 74 | { 75 | cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 76 | if (node) memset(node,0,sizeof(cJSON)); 77 | return node; 78 | } 79 | 80 | /* Delete a cJSON structure. */ 81 | void cJSON_Delete(cJSON *c) 82 | { 83 | cJSON *next; 84 | while (c) 85 | { 86 | next=c->next; 87 | if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 88 | if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 89 | if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); 90 | cJSON_free(c); 91 | c=next; 92 | } 93 | } 94 | 95 | /* Parse the input text to generate a number, and populate the result into item. */ 96 | static const char *parse_number(cJSON *item,const char *num) 97 | { 98 | double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; 99 | 100 | if (*num=='-') sign=-1,num++; /* Has sign? */ 101 | if (*num=='0') num++; /* is zero */ 102 | if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ 103 | if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ 104 | if (*num=='e' || *num=='E') /* Exponent? */ 105 | { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ 106 | while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ 107 | } 108 | 109 | n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 110 | 111 | item->valuedouble=n; 112 | item->valueint=(int)n; 113 | item->type=cJSON_Number; 114 | return num; 115 | } 116 | 117 | static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } 118 | 119 | typedef struct {char *buffer; int length; int offset; } printbuffer; 120 | 121 | static char* ensure(printbuffer *p,int needed) 122 | { 123 | char *newbuffer;int newsize; 124 | if (!p || !p->buffer) return 0; 125 | needed+=p->offset; 126 | if (needed<=p->length) return p->buffer+p->offset; 127 | 128 | newsize=pow2gt(needed); 129 | newbuffer=(char*)cJSON_malloc(newsize); 130 | if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} 131 | if (newbuffer) memcpy(newbuffer,p->buffer,p->length); 132 | cJSON_free(p->buffer); 133 | p->length=newsize; 134 | p->buffer=newbuffer; 135 | return newbuffer+p->offset; 136 | } 137 | 138 | static int update(printbuffer *p) 139 | { 140 | char *str; 141 | if (!p || !p->buffer) return 0; 142 | str=p->buffer+p->offset; 143 | return p->offset+strlen(str); 144 | } 145 | 146 | /* Render the number nicely from the given item into a string. */ 147 | static char *print_number(cJSON *item,printbuffer *p) 148 | { 149 | char *str=0; 150 | double d=item->valuedouble; 151 | if (d==0) 152 | { 153 | if (p) str=ensure(p,2); 154 | else str=(char*)cJSON_malloc(2); /* special case for 0. */ 155 | if (str) strcpy(str,"0"); 156 | } 157 | else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 158 | { 159 | if (p) str=ensure(p,21); 160 | else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ 161 | if (str) sprintf(str,"%d",item->valueint); 162 | } 163 | else 164 | { 165 | if (p) str=ensure(p,64); 166 | else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ 167 | if (str) 168 | { 169 | if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); 170 | else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); 171 | else sprintf(str,"%f",d); 172 | } 173 | } 174 | return str; 175 | } 176 | 177 | static unsigned parse_hex4(const char *str) 178 | { 179 | unsigned h=0; 180 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 181 | h=h<<4;str++; 182 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 183 | h=h<<4;str++; 184 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 185 | h=h<<4;str++; 186 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 187 | return h; 188 | } 189 | 190 | /* Parse the input text into an unescaped cstring, and populate item. */ 191 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 192 | static const char *parse_string(cJSON *item,const char *str) 193 | { 194 | const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; 195 | if (*str!='\"') {ep=str;return 0;} /* not a string! */ 196 | 197 | while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ 198 | 199 | out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 200 | if (!out) return 0; 201 | 202 | ptr=str+1;ptr2=out; 203 | while (*ptr!='\"' && *ptr) 204 | { 205 | if (*ptr!='\\') *ptr2++=*ptr++; 206 | else 207 | { 208 | ptr++; 209 | switch (*ptr) 210 | { 211 | case 'b': *ptr2++='\b'; break; 212 | case 'f': *ptr2++='\f'; break; 213 | case 'n': *ptr2++='\n'; break; 214 | case 'r': *ptr2++='\r'; break; 215 | case 't': *ptr2++='\t'; break; 216 | case 'u': /* transcode utf16 to utf8. */ 217 | uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ 218 | 219 | if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ 220 | 221 | if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ 222 | { 223 | if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ 224 | uc2=parse_hex4(ptr+3);ptr+=6; 225 | if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ 226 | uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 227 | } 228 | 229 | len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; 230 | 231 | switch (len) { 232 | case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 233 | case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 234 | case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 235 | case 1: *--ptr2 =(uc | firstByteMark[len]); 236 | } 237 | ptr2+=len; 238 | break; 239 | default: *ptr2++=*ptr; break; 240 | } 241 | ptr++; 242 | } 243 | } 244 | *ptr2=0; 245 | if (*ptr=='\"') ptr++; 246 | item->valuestring=out; 247 | item->type=cJSON_String; 248 | return ptr; 249 | } 250 | 251 | /* Render the cstring provided to an escaped version that can be printed. */ 252 | static char *print_string_ptr(const char *str,printbuffer *p) 253 | { 254 | const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; 255 | 256 | for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; 257 | if (!flag) 258 | { 259 | len=ptr-str; 260 | if (p) out=ensure(p,len+3); 261 | else out=(char*)cJSON_malloc(len+3); 262 | if (!out) return 0; 263 | ptr2=out;*ptr2++='\"'; 264 | strcpy(ptr2,str); 265 | ptr2[len]='\"'; 266 | ptr2[len+1]=0; 267 | return out; 268 | } 269 | 270 | if (!str) 271 | { 272 | if (p) out=ensure(p,3); 273 | else out=(char*)cJSON_malloc(3); 274 | if (!out) return 0; 275 | strcpy(out,"\"\""); 276 | return out; 277 | } 278 | ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} 279 | 280 | if (p) out=ensure(p,len+3); 281 | else out=(char*)cJSON_malloc(len+3); 282 | if (!out) return 0; 283 | 284 | ptr2=out;ptr=str; 285 | *ptr2++='\"'; 286 | while (*ptr) 287 | { 288 | if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; 289 | else 290 | { 291 | *ptr2++='\\'; 292 | switch (token=*ptr++) 293 | { 294 | case '\\': *ptr2++='\\'; break; 295 | case '\"': *ptr2++='\"'; break; 296 | case '\b': *ptr2++='b'; break; 297 | case '\f': *ptr2++='f'; break; 298 | case '\n': *ptr2++='n'; break; 299 | case '\r': *ptr2++='r'; break; 300 | case '\t': *ptr2++='t'; break; 301 | default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ 302 | } 303 | } 304 | } 305 | *ptr2++='\"';*ptr2++=0; 306 | return out; 307 | } 308 | /* Invote print_string_ptr (which is useful) on an item. */ 309 | static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} 310 | 311 | /* Predeclare these prototypes. */ 312 | static const char *parse_value(cJSON *item,const char *value); 313 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); 314 | static const char *parse_array(cJSON *item,const char *value); 315 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); 316 | static const char *parse_object(cJSON *item,const char *value); 317 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); 318 | 319 | /* Utility to jump whitespace and cr/lf */ 320 | static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} 321 | 322 | /* Parse an object - create a new root, and populate. */ 323 | cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) 324 | { 325 | const char *end=0; 326 | cJSON *c=cJSON_New_Item(); 327 | ep=0; 328 | if (!c) return 0; /* memory fail */ 329 | 330 | end=parse_value(c,skip(value)); 331 | if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ 332 | 333 | /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 334 | if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} 335 | if (return_parse_end) *return_parse_end=end; 336 | return c; 337 | } 338 | /* Default options for cJSON_Parse */ 339 | cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} 340 | 341 | /* Render a cJSON item/entity/structure to text. */ 342 | char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} 343 | char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} 344 | 345 | char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) 346 | { 347 | printbuffer p; 348 | p.buffer=(char*)cJSON_malloc(prebuffer); 349 | p.length=prebuffer; 350 | p.offset=0; 351 | return print_value(item,0,fmt,&p); 352 | return p.buffer; 353 | } 354 | 355 | 356 | /* Parser core - when encountering text, process appropriately. */ 357 | static const char *parse_value(cJSON *item,const char *value) 358 | { 359 | if (!value) return 0; /* Fail on null. */ 360 | if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } 361 | if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 362 | if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } 363 | if (*value=='\"') { return parse_string(item,value); } 364 | if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } 365 | if (*value=='[') { return parse_array(item,value); } 366 | if (*value=='{') { return parse_object(item,value); } 367 | 368 | ep=value;return 0; /* failure. */ 369 | } 370 | 371 | /* Render a value to text. */ 372 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) 373 | { 374 | char *out=0; 375 | if (!item) return 0; 376 | if (p) 377 | { 378 | switch ((item->type)&255) 379 | { 380 | case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} 381 | case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} 382 | case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} 383 | case cJSON_Number: out=print_number(item,p);break; 384 | case cJSON_String: out=print_string(item,p);break; 385 | case cJSON_Array: out=print_array(item,depth,fmt,p);break; 386 | case cJSON_Object: out=print_object(item,depth,fmt,p);break; 387 | } 388 | } 389 | else 390 | { 391 | switch ((item->type)&255) 392 | { 393 | case cJSON_NULL: out=cJSON_strdup("null"); break; 394 | case cJSON_False: out=cJSON_strdup("false");break; 395 | case cJSON_True: out=cJSON_strdup("true"); break; 396 | case cJSON_Number: out=print_number(item,0);break; 397 | case cJSON_String: out=print_string(item,0);break; 398 | case cJSON_Array: out=print_array(item,depth,fmt,0);break; 399 | case cJSON_Object: out=print_object(item,depth,fmt,0);break; 400 | } 401 | } 402 | return out; 403 | } 404 | 405 | /* Build an array from input text. */ 406 | static const char *parse_array(cJSON *item,const char *value) 407 | { 408 | cJSON *child; 409 | if (*value!='[') {ep=value;return 0;} /* not an array! */ 410 | 411 | item->type=cJSON_Array; 412 | value=skip(value+1); 413 | if (*value==']') return value+1; /* empty array. */ 414 | 415 | item->child=child=cJSON_New_Item(); 416 | if (!item->child) return 0; /* memory fail */ 417 | value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 418 | if (!value) return 0; 419 | 420 | while (*value==',') 421 | { 422 | cJSON *new_item; 423 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 424 | child->next=new_item;new_item->prev=child;child=new_item; 425 | value=skip(parse_value(child,skip(value+1))); 426 | if (!value) return 0; /* memory fail */ 427 | } 428 | 429 | if (*value==']') return value+1; /* end of array */ 430 | ep=value;return 0; /* malformed. */ 431 | } 432 | 433 | /* Render an array to text */ 434 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) 435 | { 436 | char **entries; 437 | char *out=0,*ptr,*ret;int len=5; 438 | cJSON *child=item->child; 439 | int numentries=0,i=0,fail=0; 440 | size_t tmplen=0; 441 | 442 | /* How many entries in the array? */ 443 | while (child) numentries++,child=child->next; 444 | /* Explicitly handle numentries==0 */ 445 | if (!numentries) 446 | { 447 | if (p) out=ensure(p,3); 448 | else out=(char*)cJSON_malloc(3); 449 | if (out) strcpy(out,"[]"); 450 | return out; 451 | } 452 | 453 | if (p) 454 | { 455 | /* Compose the output array. */ 456 | i=p->offset; 457 | ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; 458 | child=item->child; 459 | while (child && !fail) 460 | { 461 | print_value(child,depth+1,fmt,p); 462 | p->offset=update(p); 463 | if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} 464 | child=child->next; 465 | } 466 | ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; 467 | out=(p->buffer)+i; 468 | } 469 | else 470 | { 471 | /* Allocate an array to hold the values for each */ 472 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 473 | if (!entries) return 0; 474 | memset(entries,0,numentries*sizeof(char*)); 475 | /* Retrieve all the results: */ 476 | child=item->child; 477 | while (child && !fail) 478 | { 479 | ret=print_value(child,depth+1,fmt,0); 480 | entries[i++]=ret; 481 | if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 482 | child=child->next; 483 | } 484 | 485 | /* If we didn't fail, try to malloc the output string */ 486 | if (!fail) out=(char*)cJSON_malloc(len); 487 | /* If that fails, we fail. */ 488 | if (!out) fail=1; 489 | 490 | /* Handle failure. */ 491 | if (fail) 492 | { 493 | for (i=0;itype=cJSON_Object; 520 | value=skip(value+1); 521 | if (*value=='}') return value+1; /* empty array. */ 522 | 523 | item->child=child=cJSON_New_Item(); 524 | if (!item->child) return 0; 525 | value=skip(parse_string(child,skip(value))); 526 | if (!value) return 0; 527 | child->string=child->valuestring;child->valuestring=0; 528 | if (*value!=':') {ep=value;return 0;} /* fail! */ 529 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 530 | if (!value) return 0; 531 | 532 | while (*value==',') 533 | { 534 | cJSON *new_item; 535 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 536 | child->next=new_item;new_item->prev=child;child=new_item; 537 | value=skip(parse_string(child,skip(value+1))); 538 | if (!value) return 0; 539 | child->string=child->valuestring;child->valuestring=0; 540 | if (*value!=':') {ep=value;return 0;} /* fail! */ 541 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 542 | if (!value) return 0; 543 | } 544 | 545 | if (*value=='}') return value+1; /* end of array */ 546 | ep=value;return 0; /* malformed. */ 547 | } 548 | 549 | /* Render an object to text. */ 550 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) 551 | { 552 | char **entries=0,**names=0; 553 | char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 554 | cJSON *child=item->child; 555 | int numentries=0,fail=0; 556 | size_t tmplen=0; 557 | /* Count the number of entries. */ 558 | while (child) numentries++,child=child->next; 559 | /* Explicitly handle empty object case */ 560 | if (!numentries) 561 | { 562 | if (p) out=ensure(p,fmt?depth+4:3); 563 | else out=(char*)cJSON_malloc(fmt?depth+4:3); 564 | if (!out) return 0; 565 | ptr=out;*ptr++='{'; 566 | if (fmt) {*ptr++='\n';for (i=0;ioffset; 574 | len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; 575 | *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; 576 | child=item->child;depth++; 577 | while (child) 578 | { 579 | if (fmt) 580 | { 581 | ptr=ensure(p,depth); if (!ptr) return 0; 582 | for (j=0;joffset+=depth; 584 | } 585 | print_string_ptr(child->string,p); 586 | p->offset=update(p); 587 | 588 | len=fmt?2:1; 589 | ptr=ensure(p,len); if (!ptr) return 0; 590 | *ptr++=':';if (fmt) *ptr++='\t'; 591 | p->offset+=len; 592 | 593 | print_value(child,depth,fmt,p); 594 | p->offset=update(p); 595 | 596 | len=(fmt?1:0)+(child->next?1:0); 597 | ptr=ensure(p,len+1); if (!ptr) return 0; 598 | if (child->next) *ptr++=','; 599 | if (fmt) *ptr++='\n';*ptr=0; 600 | p->offset+=len; 601 | child=child->next; 602 | } 603 | ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; 604 | if (fmt) for (i=0;ibuffer)+i; 607 | } 608 | else 609 | { 610 | /* Allocate space for the names and the objects */ 611 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 612 | if (!entries) return 0; 613 | names=(char**)cJSON_malloc(numentries*sizeof(char*)); 614 | if (!names) {cJSON_free(entries);return 0;} 615 | memset(entries,0,sizeof(char*)*numentries); 616 | memset(names,0,sizeof(char*)*numentries); 617 | 618 | /* Collect all the results into our arrays: */ 619 | child=item->child;depth++;if (fmt) len+=depth; 620 | while (child) 621 | { 622 | names[i]=str=print_string_ptr(child->string,0); 623 | entries[i++]=ret=print_value(child,depth,fmt,0); 624 | if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 625 | child=child->next; 626 | } 627 | 628 | /* Try to allocate the output string */ 629 | if (!fail) out=(char*)cJSON_malloc(len); 630 | if (!out) fail=1; 631 | 632 | /* Handle failure */ 633 | if (fail) 634 | { 635 | for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} 662 | cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} 663 | cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} 664 | 665 | /* Utility for array list handling. */ 666 | static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} 667 | /* Utility for handling references. */ 668 | static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 669 | 670 | /* Add item to array/object. */ 671 | void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} 672 | void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} 673 | void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} 674 | void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} 675 | void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} 676 | 677 | cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; 678 | if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} 679 | void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} 680 | cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} 681 | void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} 682 | 683 | /* Replace array/object items with new ones. */ 684 | void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} 685 | newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} 686 | void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; 687 | newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; 688 | if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} 689 | void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} 690 | 691 | /* Create basic types: */ 692 | cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} 693 | cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} 694 | cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} 695 | cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} 696 | cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} 697 | cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} 698 | cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} 699 | cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} 700 | 701 | /* Create Arrays: */ 702 | cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 703 | cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 704 | cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 705 | cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 706 | 707 | /* Duplication */ 708 | cJSON *cJSON_Duplicate(cJSON *item,int recurse) 709 | { 710 | cJSON *newitem,*cptr,*nptr=0,*newchild; 711 | /* Bail on bad ptr */ 712 | if (!item) return 0; 713 | /* Create new item */ 714 | newitem=cJSON_New_Item(); 715 | if (!newitem) return 0; 716 | /* Copy over all vars */ 717 | newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; 718 | if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} 719 | if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} 720 | /* If non-recursive, then we're done! */ 721 | if (!recurse) return newitem; 722 | /* Walk the ->next chain for the child. */ 723 | cptr=item->child; 724 | while (cptr) 725 | { 726 | newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ 727 | if (!newchild) {cJSON_Delete(newitem);return 0;} 728 | if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 729 | else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ 730 | cptr=cptr->next; 731 | } 732 | return newitem; 733 | } 734 | 735 | void cJSON_Minify(char *json) 736 | { 737 | char *into=json; 738 | while (*json) 739 | { 740 | if (*json==' ') json++; 741 | else if (*json=='\t') json++; /* Whitespace characters. */ 742 | else if (*json=='\r') json++; 743 | else if (*json=='\n') json++; 744 | else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ 745 | else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ 746 | else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ 747 | else *into++=*json++; /* All other characters. */ 748 | } 749 | *into=0; /* and null-terminate. */ 750 | } 751 | -------------------------------------------------------------------------------- /login/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 | #define cJSON_StringIsConst 512 42 | 43 | #include 44 | 45 | /* The cJSON structure: */ 46 | typedef struct cJSON { 47 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 48 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 49 | 50 | int type; /* The type of the item, as above. */ 51 | 52 | char *valuestring; /* The item's string, if type==cJSON_String */ 53 | int valueint; /* The item's number, if type==cJSON_Number */ 54 | double valuedouble; /* The item's number, if type==cJSON_Number */ 55 | 56 | char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 57 | } cJSON; 58 | 59 | typedef struct cJSON_Hooks { 60 | void *(*malloc_fn)(size_t sz); 61 | void (*free_fn)(void *ptr); 62 | } cJSON_Hooks; 63 | 64 | /* Supply malloc, realloc and free functions to cJSON */ 65 | extern void cJSON_InitHooks(cJSON_Hooks* hooks); 66 | 67 | 68 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ 69 | extern cJSON *cJSON_Parse(const char *value); 70 | /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ 71 | extern char *cJSON_Print(cJSON *item); 72 | /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ 73 | extern char *cJSON_PrintUnformatted(cJSON *item); 74 | /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ 75 | extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); 76 | /* Delete a cJSON entity and all subentities. */ 77 | extern void cJSON_Delete(cJSON *c); 78 | 79 | /* Returns the number of items in an array (or object). */ 80 | extern int cJSON_GetArraySize(cJSON *array); 81 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 82 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 83 | /* Get item "string" from object. Case insensitive. */ 84 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 85 | 86 | /* 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. */ 87 | extern const char *cJSON_GetErrorPtr(void); 88 | 89 | /* These calls create a cJSON item of the appropriate type. */ 90 | extern cJSON *cJSON_CreateNull(void); 91 | extern cJSON *cJSON_CreateTrue(void); 92 | extern cJSON *cJSON_CreateFalse(void); 93 | extern cJSON *cJSON_CreateBool(int b); 94 | extern cJSON *cJSON_CreateNumber(double num); 95 | extern cJSON *cJSON_CreateString(const char *string); 96 | extern cJSON *cJSON_CreateArray(void); 97 | extern cJSON *cJSON_CreateObject(void); 98 | 99 | /* These utilities create an Array of count items. */ 100 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 101 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 102 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 103 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 104 | 105 | /* Append item to the specified array/object. */ 106 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 107 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 108 | extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ 109 | /* 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. */ 110 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 111 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 112 | 113 | /* Remove/Detatch items from Arrays/Objects. */ 114 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 115 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 116 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 117 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 118 | 119 | /* Update array items. */ 120 | extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ 121 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 122 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 123 | 124 | /* Duplicate a cJSON item */ 125 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 126 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 127 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 128 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 129 | 130 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 131 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 132 | 133 | extern void cJSON_Minify(char *json); 134 | 135 | /* Macros for creating things quickly. */ 136 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 137 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 138 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 139 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 140 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 141 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 142 | 143 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 144 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 145 | #define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 146 | 147 | #ifdef __cplusplus 148 | } 149 | #endif 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /login/login.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldw0215/libcurl/dbc3d297a3168b8e13dc91ab2232c650104251a3/login/login.cpp -------------------------------------------------------------------------------- /login_https/cJSON.cpp: -------------------------------------------------------------------------------- 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 | /* cJSON */ 24 | /* JSON parser in C. */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "cJSON.h" 34 | 35 | static const char *ep; 36 | 37 | const char *cJSON_GetErrorPtr(void) {return ep;} 38 | 39 | static int cJSON_strcasecmp(const char *s1,const char *s2) 40 | { 41 | if (!s1) return (s1==s2)?0:1;if (!s2) return 1; 42 | for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; 43 | return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); 44 | } 45 | 46 | static void *(*cJSON_malloc)(size_t sz) = malloc; 47 | static void (*cJSON_free)(void *ptr) = free; 48 | 49 | static char* cJSON_strdup(const char* str) 50 | { 51 | size_t len; 52 | char* copy; 53 | 54 | len = strlen(str) + 1; 55 | if (!(copy = (char*)cJSON_malloc(len))) return 0; 56 | memcpy(copy,str,len); 57 | return copy; 58 | } 59 | 60 | void cJSON_InitHooks(cJSON_Hooks* hooks) 61 | { 62 | if (!hooks) { /* Reset hooks */ 63 | cJSON_malloc = malloc; 64 | cJSON_free = free; 65 | return; 66 | } 67 | 68 | cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 69 | cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 70 | } 71 | 72 | /* Internal constructor. */ 73 | static cJSON *cJSON_New_Item(void) 74 | { 75 | cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 76 | if (node) memset(node,0,sizeof(cJSON)); 77 | return node; 78 | } 79 | 80 | /* Delete a cJSON structure. */ 81 | void cJSON_Delete(cJSON *c) 82 | { 83 | cJSON *next; 84 | while (c) 85 | { 86 | next=c->next; 87 | if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 88 | if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 89 | if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); 90 | cJSON_free(c); 91 | c=next; 92 | } 93 | } 94 | 95 | /* Parse the input text to generate a number, and populate the result into item. */ 96 | static const char *parse_number(cJSON *item,const char *num) 97 | { 98 | double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; 99 | 100 | if (*num=='-') sign=-1,num++; /* Has sign? */ 101 | if (*num=='0') num++; /* is zero */ 102 | if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ 103 | if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ 104 | if (*num=='e' || *num=='E') /* Exponent? */ 105 | { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ 106 | while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ 107 | } 108 | 109 | n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 110 | 111 | item->valuedouble=n; 112 | item->valueint=(int)n; 113 | item->type=cJSON_Number; 114 | return num; 115 | } 116 | 117 | static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } 118 | 119 | typedef struct {char *buffer; int length; int offset; } printbuffer; 120 | 121 | static char* ensure(printbuffer *p,int needed) 122 | { 123 | char *newbuffer;int newsize; 124 | if (!p || !p->buffer) return 0; 125 | needed+=p->offset; 126 | if (needed<=p->length) return p->buffer+p->offset; 127 | 128 | newsize=pow2gt(needed); 129 | newbuffer=(char*)cJSON_malloc(newsize); 130 | if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} 131 | if (newbuffer) memcpy(newbuffer,p->buffer,p->length); 132 | cJSON_free(p->buffer); 133 | p->length=newsize; 134 | p->buffer=newbuffer; 135 | return newbuffer+p->offset; 136 | } 137 | 138 | static int update(printbuffer *p) 139 | { 140 | char *str; 141 | if (!p || !p->buffer) return 0; 142 | str=p->buffer+p->offset; 143 | return p->offset+strlen(str); 144 | } 145 | 146 | /* Render the number nicely from the given item into a string. */ 147 | static char *print_number(cJSON *item,printbuffer *p) 148 | { 149 | char *str=0; 150 | double d=item->valuedouble; 151 | if (d==0) 152 | { 153 | if (p) str=ensure(p,2); 154 | else str=(char*)cJSON_malloc(2); /* special case for 0. */ 155 | if (str) strcpy(str,"0"); 156 | } 157 | else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 158 | { 159 | if (p) str=ensure(p,21); 160 | else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ 161 | if (str) sprintf(str,"%d",item->valueint); 162 | } 163 | else 164 | { 165 | if (p) str=ensure(p,64); 166 | else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ 167 | if (str) 168 | { 169 | if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); 170 | else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); 171 | else sprintf(str,"%f",d); 172 | } 173 | } 174 | return str; 175 | } 176 | 177 | static unsigned parse_hex4(const char *str) 178 | { 179 | unsigned h=0; 180 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 181 | h=h<<4;str++; 182 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 183 | h=h<<4;str++; 184 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 185 | h=h<<4;str++; 186 | if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; 187 | return h; 188 | } 189 | 190 | /* Parse the input text into an unescaped cstring, and populate item. */ 191 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 192 | static const char *parse_string(cJSON *item,const char *str) 193 | { 194 | const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; 195 | if (*str!='\"') {ep=str;return 0;} /* not a string! */ 196 | 197 | while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ 198 | 199 | out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 200 | if (!out) return 0; 201 | 202 | ptr=str+1;ptr2=out; 203 | while (*ptr!='\"' && *ptr) 204 | { 205 | if (*ptr!='\\') *ptr2++=*ptr++; 206 | else 207 | { 208 | ptr++; 209 | switch (*ptr) 210 | { 211 | case 'b': *ptr2++='\b'; break; 212 | case 'f': *ptr2++='\f'; break; 213 | case 'n': *ptr2++='\n'; break; 214 | case 'r': *ptr2++='\r'; break; 215 | case 't': *ptr2++='\t'; break; 216 | case 'u': /* transcode utf16 to utf8. */ 217 | uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ 218 | 219 | if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ 220 | 221 | if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ 222 | { 223 | if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ 224 | uc2=parse_hex4(ptr+3);ptr+=6; 225 | if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ 226 | uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 227 | } 228 | 229 | len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; 230 | 231 | switch (len) { 232 | case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 233 | case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 234 | case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 235 | case 1: *--ptr2 =(uc | firstByteMark[len]); 236 | } 237 | ptr2+=len; 238 | break; 239 | default: *ptr2++=*ptr; break; 240 | } 241 | ptr++; 242 | } 243 | } 244 | *ptr2=0; 245 | if (*ptr=='\"') ptr++; 246 | item->valuestring=out; 247 | item->type=cJSON_String; 248 | return ptr; 249 | } 250 | 251 | /* Render the cstring provided to an escaped version that can be printed. */ 252 | static char *print_string_ptr(const char *str,printbuffer *p) 253 | { 254 | const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; 255 | 256 | for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; 257 | if (!flag) 258 | { 259 | len=ptr-str; 260 | if (p) out=ensure(p,len+3); 261 | else out=(char*)cJSON_malloc(len+3); 262 | if (!out) return 0; 263 | ptr2=out;*ptr2++='\"'; 264 | strcpy(ptr2,str); 265 | ptr2[len]='\"'; 266 | ptr2[len+1]=0; 267 | return out; 268 | } 269 | 270 | if (!str) 271 | { 272 | if (p) out=ensure(p,3); 273 | else out=(char*)cJSON_malloc(3); 274 | if (!out) return 0; 275 | strcpy(out,"\"\""); 276 | return out; 277 | } 278 | ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} 279 | 280 | if (p) out=ensure(p,len+3); 281 | else out=(char*)cJSON_malloc(len+3); 282 | if (!out) return 0; 283 | 284 | ptr2=out;ptr=str; 285 | *ptr2++='\"'; 286 | while (*ptr) 287 | { 288 | if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; 289 | else 290 | { 291 | *ptr2++='\\'; 292 | switch (token=*ptr++) 293 | { 294 | case '\\': *ptr2++='\\'; break; 295 | case '\"': *ptr2++='\"'; break; 296 | case '\b': *ptr2++='b'; break; 297 | case '\f': *ptr2++='f'; break; 298 | case '\n': *ptr2++='n'; break; 299 | case '\r': *ptr2++='r'; break; 300 | case '\t': *ptr2++='t'; break; 301 | default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ 302 | } 303 | } 304 | } 305 | *ptr2++='\"';*ptr2++=0; 306 | return out; 307 | } 308 | /* Invote print_string_ptr (which is useful) on an item. */ 309 | static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} 310 | 311 | /* Predeclare these prototypes. */ 312 | static const char *parse_value(cJSON *item,const char *value); 313 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); 314 | static const char *parse_array(cJSON *item,const char *value); 315 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); 316 | static const char *parse_object(cJSON *item,const char *value); 317 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); 318 | 319 | /* Utility to jump whitespace and cr/lf */ 320 | static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} 321 | 322 | /* Parse an object - create a new root, and populate. */ 323 | cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) 324 | { 325 | const char *end=0; 326 | cJSON *c=cJSON_New_Item(); 327 | ep=0; 328 | if (!c) return 0; /* memory fail */ 329 | 330 | end=parse_value(c,skip(value)); 331 | if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ 332 | 333 | /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 334 | if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} 335 | if (return_parse_end) *return_parse_end=end; 336 | return c; 337 | } 338 | /* Default options for cJSON_Parse */ 339 | cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} 340 | 341 | /* Render a cJSON item/entity/structure to text. */ 342 | char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} 343 | char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} 344 | 345 | char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) 346 | { 347 | printbuffer p; 348 | p.buffer=(char*)cJSON_malloc(prebuffer); 349 | p.length=prebuffer; 350 | p.offset=0; 351 | return print_value(item,0,fmt,&p); 352 | return p.buffer; 353 | } 354 | 355 | 356 | /* Parser core - when encountering text, process appropriately. */ 357 | static const char *parse_value(cJSON *item,const char *value) 358 | { 359 | if (!value) return 0; /* Fail on null. */ 360 | if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } 361 | if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 362 | if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } 363 | if (*value=='\"') { return parse_string(item,value); } 364 | if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } 365 | if (*value=='[') { return parse_array(item,value); } 366 | if (*value=='{') { return parse_object(item,value); } 367 | 368 | ep=value;return 0; /* failure. */ 369 | } 370 | 371 | /* Render a value to text. */ 372 | static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) 373 | { 374 | char *out=0; 375 | if (!item) return 0; 376 | if (p) 377 | { 378 | switch ((item->type)&255) 379 | { 380 | case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} 381 | case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} 382 | case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} 383 | case cJSON_Number: out=print_number(item,p);break; 384 | case cJSON_String: out=print_string(item,p);break; 385 | case cJSON_Array: out=print_array(item,depth,fmt,p);break; 386 | case cJSON_Object: out=print_object(item,depth,fmt,p);break; 387 | } 388 | } 389 | else 390 | { 391 | switch ((item->type)&255) 392 | { 393 | case cJSON_NULL: out=cJSON_strdup("null"); break; 394 | case cJSON_False: out=cJSON_strdup("false");break; 395 | case cJSON_True: out=cJSON_strdup("true"); break; 396 | case cJSON_Number: out=print_number(item,0);break; 397 | case cJSON_String: out=print_string(item,0);break; 398 | case cJSON_Array: out=print_array(item,depth,fmt,0);break; 399 | case cJSON_Object: out=print_object(item,depth,fmt,0);break; 400 | } 401 | } 402 | return out; 403 | } 404 | 405 | /* Build an array from input text. */ 406 | static const char *parse_array(cJSON *item,const char *value) 407 | { 408 | cJSON *child; 409 | if (*value!='[') {ep=value;return 0;} /* not an array! */ 410 | 411 | item->type=cJSON_Array; 412 | value=skip(value+1); 413 | if (*value==']') return value+1; /* empty array. */ 414 | 415 | item->child=child=cJSON_New_Item(); 416 | if (!item->child) return 0; /* memory fail */ 417 | value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 418 | if (!value) return 0; 419 | 420 | while (*value==',') 421 | { 422 | cJSON *new_item; 423 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 424 | child->next=new_item;new_item->prev=child;child=new_item; 425 | value=skip(parse_value(child,skip(value+1))); 426 | if (!value) return 0; /* memory fail */ 427 | } 428 | 429 | if (*value==']') return value+1; /* end of array */ 430 | ep=value;return 0; /* malformed. */ 431 | } 432 | 433 | /* Render an array to text */ 434 | static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) 435 | { 436 | char **entries; 437 | char *out=0,*ptr,*ret;int len=5; 438 | cJSON *child=item->child; 439 | int numentries=0,i=0,fail=0; 440 | size_t tmplen=0; 441 | 442 | /* How many entries in the array? */ 443 | while (child) numentries++,child=child->next; 444 | /* Explicitly handle numentries==0 */ 445 | if (!numentries) 446 | { 447 | if (p) out=ensure(p,3); 448 | else out=(char*)cJSON_malloc(3); 449 | if (out) strcpy(out,"[]"); 450 | return out; 451 | } 452 | 453 | if (p) 454 | { 455 | /* Compose the output array. */ 456 | i=p->offset; 457 | ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; 458 | child=item->child; 459 | while (child && !fail) 460 | { 461 | print_value(child,depth+1,fmt,p); 462 | p->offset=update(p); 463 | if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} 464 | child=child->next; 465 | } 466 | ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; 467 | out=(p->buffer)+i; 468 | } 469 | else 470 | { 471 | /* Allocate an array to hold the values for each */ 472 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 473 | if (!entries) return 0; 474 | memset(entries,0,numentries*sizeof(char*)); 475 | /* Retrieve all the results: */ 476 | child=item->child; 477 | while (child && !fail) 478 | { 479 | ret=print_value(child,depth+1,fmt,0); 480 | entries[i++]=ret; 481 | if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 482 | child=child->next; 483 | } 484 | 485 | /* If we didn't fail, try to malloc the output string */ 486 | if (!fail) out=(char*)cJSON_malloc(len); 487 | /* If that fails, we fail. */ 488 | if (!out) fail=1; 489 | 490 | /* Handle failure. */ 491 | if (fail) 492 | { 493 | for (i=0;itype=cJSON_Object; 520 | value=skip(value+1); 521 | if (*value=='}') return value+1; /* empty array. */ 522 | 523 | item->child=child=cJSON_New_Item(); 524 | if (!item->child) return 0; 525 | value=skip(parse_string(child,skip(value))); 526 | if (!value) return 0; 527 | child->string=child->valuestring;child->valuestring=0; 528 | if (*value!=':') {ep=value;return 0;} /* fail! */ 529 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 530 | if (!value) return 0; 531 | 532 | while (*value==',') 533 | { 534 | cJSON *new_item; 535 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 536 | child->next=new_item;new_item->prev=child;child=new_item; 537 | value=skip(parse_string(child,skip(value+1))); 538 | if (!value) return 0; 539 | child->string=child->valuestring;child->valuestring=0; 540 | if (*value!=':') {ep=value;return 0;} /* fail! */ 541 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 542 | if (!value) return 0; 543 | } 544 | 545 | if (*value=='}') return value+1; /* end of array */ 546 | ep=value;return 0; /* malformed. */ 547 | } 548 | 549 | /* Render an object to text. */ 550 | static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) 551 | { 552 | char **entries=0,**names=0; 553 | char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 554 | cJSON *child=item->child; 555 | int numentries=0,fail=0; 556 | size_t tmplen=0; 557 | /* Count the number of entries. */ 558 | while (child) numentries++,child=child->next; 559 | /* Explicitly handle empty object case */ 560 | if (!numentries) 561 | { 562 | if (p) out=ensure(p,fmt?depth+4:3); 563 | else out=(char*)cJSON_malloc(fmt?depth+4:3); 564 | if (!out) return 0; 565 | ptr=out;*ptr++='{'; 566 | if (fmt) {*ptr++='\n';for (i=0;ioffset; 574 | len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; 575 | *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; 576 | child=item->child;depth++; 577 | while (child) 578 | { 579 | if (fmt) 580 | { 581 | ptr=ensure(p,depth); if (!ptr) return 0; 582 | for (j=0;joffset+=depth; 584 | } 585 | print_string_ptr(child->string,p); 586 | p->offset=update(p); 587 | 588 | len=fmt?2:1; 589 | ptr=ensure(p,len); if (!ptr) return 0; 590 | *ptr++=':';if (fmt) *ptr++='\t'; 591 | p->offset+=len; 592 | 593 | print_value(child,depth,fmt,p); 594 | p->offset=update(p); 595 | 596 | len=(fmt?1:0)+(child->next?1:0); 597 | ptr=ensure(p,len+1); if (!ptr) return 0; 598 | if (child->next) *ptr++=','; 599 | if (fmt) *ptr++='\n';*ptr=0; 600 | p->offset+=len; 601 | child=child->next; 602 | } 603 | ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; 604 | if (fmt) for (i=0;ibuffer)+i; 607 | } 608 | else 609 | { 610 | /* Allocate space for the names and the objects */ 611 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 612 | if (!entries) return 0; 613 | names=(char**)cJSON_malloc(numentries*sizeof(char*)); 614 | if (!names) {cJSON_free(entries);return 0;} 615 | memset(entries,0,sizeof(char*)*numentries); 616 | memset(names,0,sizeof(char*)*numentries); 617 | 618 | /* Collect all the results into our arrays: */ 619 | child=item->child;depth++;if (fmt) len+=depth; 620 | while (child) 621 | { 622 | names[i]=str=print_string_ptr(child->string,0); 623 | entries[i++]=ret=print_value(child,depth,fmt,0); 624 | if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 625 | child=child->next; 626 | } 627 | 628 | /* Try to allocate the output string */ 629 | if (!fail) out=(char*)cJSON_malloc(len); 630 | if (!out) fail=1; 631 | 632 | /* Handle failure */ 633 | if (fail) 634 | { 635 | for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} 662 | cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} 663 | cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} 664 | 665 | /* Utility for array list handling. */ 666 | static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} 667 | /* Utility for handling references. */ 668 | static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 669 | 670 | /* Add item to array/object. */ 671 | void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} 672 | void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} 673 | void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} 674 | void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} 675 | void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} 676 | 677 | cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; 678 | if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} 679 | void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} 680 | cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} 681 | void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} 682 | 683 | /* Replace array/object items with new ones. */ 684 | void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} 685 | newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} 686 | void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; 687 | newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; 688 | if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} 689 | void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} 690 | 691 | /* Create basic types: */ 692 | cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} 693 | cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} 694 | cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} 695 | cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} 696 | cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} 697 | cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} 698 | cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} 699 | cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} 700 | 701 | /* Create Arrays: */ 702 | cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 703 | cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 704 | cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 705 | cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 706 | 707 | /* Duplication */ 708 | cJSON *cJSON_Duplicate(cJSON *item,int recurse) 709 | { 710 | cJSON *newitem,*cptr,*nptr=0,*newchild; 711 | /* Bail on bad ptr */ 712 | if (!item) return 0; 713 | /* Create new item */ 714 | newitem=cJSON_New_Item(); 715 | if (!newitem) return 0; 716 | /* Copy over all vars */ 717 | newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; 718 | if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} 719 | if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} 720 | /* If non-recursive, then we're done! */ 721 | if (!recurse) return newitem; 722 | /* Walk the ->next chain for the child. */ 723 | cptr=item->child; 724 | while (cptr) 725 | { 726 | newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ 727 | if (!newchild) {cJSON_Delete(newitem);return 0;} 728 | if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 729 | else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ 730 | cptr=cptr->next; 731 | } 732 | return newitem; 733 | } 734 | 735 | void cJSON_Minify(char *json) 736 | { 737 | char *into=json; 738 | while (*json) 739 | { 740 | if (*json==' ') json++; 741 | else if (*json=='\t') json++; /* Whitespace characters. */ 742 | else if (*json=='\r') json++; 743 | else if (*json=='\n') json++; 744 | else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ 745 | else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ 746 | else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ 747 | else *into++=*json++; /* All other characters. */ 748 | } 749 | *into=0; /* and null-terminate. */ 750 | } 751 | -------------------------------------------------------------------------------- /login_https/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 | #define cJSON_StringIsConst 512 42 | 43 | #include 44 | 45 | /* The cJSON structure: */ 46 | typedef struct cJSON { 47 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 48 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 49 | 50 | int type; /* The type of the item, as above. */ 51 | 52 | char *valuestring; /* The item's string, if type==cJSON_String */ 53 | int valueint; /* The item's number, if type==cJSON_Number */ 54 | double valuedouble; /* The item's number, if type==cJSON_Number */ 55 | 56 | char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 57 | } cJSON; 58 | 59 | typedef struct cJSON_Hooks { 60 | void *(*malloc_fn)(size_t sz); 61 | void (*free_fn)(void *ptr); 62 | } cJSON_Hooks; 63 | 64 | /* Supply malloc, realloc and free functions to cJSON */ 65 | extern void cJSON_InitHooks(cJSON_Hooks* hooks); 66 | 67 | 68 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ 69 | extern cJSON *cJSON_Parse(const char *value); 70 | /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ 71 | extern char *cJSON_Print(cJSON *item); 72 | /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ 73 | extern char *cJSON_PrintUnformatted(cJSON *item); 74 | /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ 75 | extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); 76 | /* Delete a cJSON entity and all subentities. */ 77 | extern void cJSON_Delete(cJSON *c); 78 | 79 | /* Returns the number of items in an array (or object). */ 80 | extern int cJSON_GetArraySize(cJSON *array); 81 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 82 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 83 | /* Get item "string" from object. Case insensitive. */ 84 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 85 | 86 | /* 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. */ 87 | extern const char *cJSON_GetErrorPtr(void); 88 | 89 | /* These calls create a cJSON item of the appropriate type. */ 90 | extern cJSON *cJSON_CreateNull(void); 91 | extern cJSON *cJSON_CreateTrue(void); 92 | extern cJSON *cJSON_CreateFalse(void); 93 | extern cJSON *cJSON_CreateBool(int b); 94 | extern cJSON *cJSON_CreateNumber(double num); 95 | extern cJSON *cJSON_CreateString(const char *string); 96 | extern cJSON *cJSON_CreateArray(void); 97 | extern cJSON *cJSON_CreateObject(void); 98 | 99 | /* These utilities create an Array of count items. */ 100 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 101 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 102 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 103 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 104 | 105 | /* Append item to the specified array/object. */ 106 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 107 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 108 | extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ 109 | /* 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. */ 110 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 111 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 112 | 113 | /* Remove/Detatch items from Arrays/Objects. */ 114 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 115 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 116 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 117 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 118 | 119 | /* Update array items. */ 120 | extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ 121 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 122 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 123 | 124 | /* Duplicate a cJSON item */ 125 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 126 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 127 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 128 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 129 | 130 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 131 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 132 | 133 | extern void cJSON_Minify(char *json); 134 | 135 | /* Macros for creating things quickly. */ 136 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 137 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 138 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 139 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 140 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 141 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 142 | 143 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 144 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 145 | #define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 146 | 147 | #ifdef __cplusplus 148 | } 149 | #endif 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /login_https/login.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldw0215/libcurl/dbc3d297a3168b8e13dc91ab2232c650104251a3/login_https/login.cpp --------------------------------------------------------------------------------