1#include "base.h" 2#include "log.h" 3#include "buffer.h" 4 5#include "plugin.h" 6 7#include <ctype.h> 8#include <stdlib.h> 9#include <string.h> 10#include <dlinklist.h> 11#include <dirent.h> 12 13#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) 14#include <sqlite3.h> 15#endif 16 17#ifdef EMBEDDED_EANBLE 18//#ifdef RTCONFIG_USB 19#include <disk_initial.h> 20//#endif 21#endif 22 23#define DBE 1 24 25typedef struct { 26 array *access_deny; 27} plugin_config; 28 29typedef struct { 30 PLUGIN_DATA; 31 32 plugin_config **config_storage; 33 34 plugin_config conf; 35} plugin_data; 36 37typedef struct folder_info_s { 38 buffer *path; 39 struct folder_info_s *prev, *next; 40}folder_info_t; 41 42typedef enum { 43 INVITE_FINISHED, 44 INVITE_ACCOUNT_EXISTED, 45 INVITE_TOKEN_INVALID, 46 INVITE_SECURITY_CODE_INVALID, 47 INVITE_ERROR 48} update_invite_t; 49 50INIT_FUNC(mod_aicloud_invite_init) { 51 plugin_data *p; 52 53 p = calloc(1, sizeof(*p)); 54 55 return p; 56} 57 58FREE_FUNC(mod_aicloud_invite_free) { 59 plugin_data *p = p_d; 60 61 UNUSED(srv); 62 63 if (!p) return HANDLER_GO_ON; 64 65 if (p->config_storage) { 66 size_t i; 67 for (i = 0; i < srv->config_context->used; i++) { 68 plugin_config *s = p->config_storage[i]; 69 70 array_free(s->access_deny); 71 72 free(s); 73 } 74 free(p->config_storage); 75 } 76 77 free(p); 78 79 return HANDLER_GO_ON; 80} 81 82SETDEFAULTS_FUNC(mod_aicloud_invite_set_defaults) { 83 plugin_data *p = p_d; 84 size_t i = 0; 85 86 config_values_t cv[] = { 87 { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, 88 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } 89 }; 90 91 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); 92 93 for (i = 0; i < srv->config_context->used; i++) { 94 plugin_config *s; 95 96 s = calloc(1, sizeof(plugin_config)); 97 s->access_deny = array_init(); 98 99 cv[0].destination = s->access_deny; 100 101 p->config_storage[i] = s; 102 103 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) { 104 return HANDLER_ERROR; 105 } 106 } 107 108 return HANDLER_GO_ON; 109} 110 111#define PATCH(x) \ 112 p->conf.x = s->x; 113static int mod_craete_captcha_image_patch_connection(server *srv, connection *con, plugin_data *p) { 114 size_t i, j; 115 plugin_config *s = p->config_storage[0]; 116 117 PATCH(access_deny); 118 119 /* skip the first, the global context */ 120 for (i = 1; i < srv->config_context->used; i++) { 121 data_config *dc = (data_config *)srv->config_context->data[i]; 122 s = p->config_storage[i]; 123 124 /* condition didn't match */ 125 if (!config_check_cond(srv, con, dc)) continue; 126 127 /* merge config */ 128 for (j = 0; j < dc->value->used; j++) { 129 data_unset *du = dc->value->data[j]; 130 131 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) { 132 PATCH(access_deny); 133 } 134 } 135 } 136 137 return 0; 138} 139#undef PATCH 140 141char* get_url_param_ualue(const char* url_param, const char* key){ 142 143 if(key==NULL || url_param==NULL) 144 return NULL; 145 146 if(strcmp(key,"")==0 || strcmp(url_param,"")==0) 147 return NULL; 148 149 buffer* buffer_param = buffer_init(); 150 buffer_copy_string(buffer_param, url_param); 151 152 char* pch = strtok(buffer_param->ptr, "&"); 153 int key_len = strlen(key); 154 char* value = NULL; 155 156 while(pch!=NULL){ 157 if(strncmp(pch, key, key_len)==0){ 158 int len = strlen(pch) - key_len - 1; 159 160 value = (char*)malloc(len+1); 161 memset(value, '\0', len); 162 strncpy(value, pch+key_len+1, len); 163 value[len]='\0'; 164 165 break; 166 } 167 168 pch = strtok( NULL, "&" ); 169 } 170 171 buffer_free(buffer_param); 172 173 return value; 174} 175 176update_invite_t update_account_invite(const char* token, const char* username, const char* password, const char* security_code){ 177 178 if(token==NULL || username==NULL || password==NULL) 179 return INVITE_ERROR; 180 181 int bFoundToken = 0; 182 aicloud_acc_invite_info_t *c; 183 for (c = aicloud_acc_invite_info_list; c; c = c->next) { 184 if(buffer_is_equal_string(c->token, token, strlen(token))){ 185 bFoundToken = 1; 186 break; 187 } 188 } 189 190 if(bFoundToken==0){ 191 return INVITE_TOKEN_INVALID; 192 } 193 194 if(c->status!=0){ 195 return INVITE_ERROR; 196 } 197 198 //- check security code 199 Cdbg(DBE, "c->security_code=%s", c->security_code->ptr); 200 if(!buffer_is_empty(c->security_code) && !buffer_is_equal_string(c->security_code, security_code, strlen(security_code))){ 201 return INVITE_SECURITY_CODE_INVALID; 202 } 203 204 //- check username 205 if(is_account_existed(username)==1){ 206 return INVITE_ACCOUNT_EXISTED; 207 } 208 209 //- add account 210 aicloud_acc_info_t *aicloud_acc_info; 211 aicloud_acc_info = (aicloud_acc_info_t *)calloc(1, sizeof(aicloud_acc_info_t)); 212 213 //- User Name 214 aicloud_acc_info->username = buffer_init(); 215 buffer_copy_string(aicloud_acc_info->username, username); 216 217 //- User Password 218 aicloud_acc_info->password = buffer_init(); 219 buffer_copy_string(aicloud_acc_info->password, password); 220 221 DLIST_ADD(aicloud_acc_info_list, aicloud_acc_info); 222 223 save_aicloud_acc_list(); 224 225 //- create permission 226 if(!buffer_is_empty(c->permission)){ 227 228 char * pch; 229 pch = strtok(c->permission->ptr, ",;"); 230 231 while(pch!=NULL){ 232 233 //- partion 234 buffer* partion = buffer_init(); 235 buffer_copy_string_len(partion, CONST_STR_LEN("/mnt/") ); 236 buffer_append_string_len(partion, pch, strlen(pch)); 237 buffer_urldecode_path(partion); 238 239 //- folder 240 pch = strtok(NULL,",;"); 241 buffer* folder = buffer_init(); 242 buffer_copy_string_len(folder, pch, strlen(pch)); 243 buffer_urldecode_path(folder); 244 245 //- permission 246 pch = strtok(NULL,",;"); 247 buffer* permission = buffer_init(); 248 buffer_copy_string_len(permission, pch, strlen(pch)); 249 250 Cdbg(DBE, "result: partion=%s, folder=%s, permission=%s", partion->ptr, folder->ptr, permission->ptr); 251 252#if EMBEDDED_EANBLE 253 set_aicloud_permission( username, 254 partion->ptr, 255 folder->ptr, 256 atoi(c->permission->ptr) ); 257#endif 258 buffer_free(partion); 259 buffer_free(folder); 260 buffer_free(permission); 261 262 pch = strtok(NULL,",;"); 263 264 } 265 266 } 267 268 //- delete invite token 269 free_aicloud_acc_invite_info(c); 270 DLIST_REMOVE(aicloud_acc_invite_info_list, c); 271 free(c); 272 273 save_aicloud_acc_invite_list(); 274 275 return INVITE_FINISHED; 276} 277 278#if 0 279int parse_postdata_from_chunkqueue(server *srv, connection *con, plugin_data *p, chunkqueue *cq, char **ret_data) { 280 281 int res = -1; 282 283 chunk *c; 284 char* result_data = NULL; 285 286 UNUSED(con); 287 288 for (c = cq->first; cq->bytes_out != cq->bytes_in; c = cq->first) { 289 size_t weWant = cq->bytes_out - cq->bytes_in; 290 size_t weHave; 291 292 switch(c->type) { 293 case MEM_CHUNK: 294 weHave = c->mem->used - 1 - c->offset; 295 296 if (weHave > weWant) weHave = weWant; 297 298 result_data = (char*)malloc(sizeof(char)*(weHave+1)); 299 memset(result_data, 0, sizeof(char)*(weHave+1)); 300 strcpy(result_data, c->mem->ptr + c->offset); 301 302 c->offset += weHave; 303 cq->bytes_out += weHave; 304 305 res = 0; 306 307 break; 308 309 default: 310 break; 311 } 312 313 chunkqueue_remove_finished_chunks(cq); 314 } 315 316 *ret_data = result_data; 317 318 return res; 319} 320#endif 321 322URIHANDLER_FUNC(mod_aicloud_invite_physical_handler){ 323 plugin_data *p = p_d; 324 int s_len; 325 size_t k; 326 int is_root_path = 0; 327 char* param_val = NULL; 328 buffer *b = NULL; 329 330 if (con->mode != SMB_BASIC&&con->mode != DIRECT) return HANDLER_GO_ON; 331 if (con->uri.path->used == 0) return HANDLER_GO_ON; 332 333 if( strncmp( con->request.uri->ptr, "/AINVITE", 7 ) != 0 ) 334 return HANDLER_GO_ON; 335 336 //- extract invite token 337 char* str = strstr(con->request.uri->ptr, "/AINVITE" ) + 1; 338 339 if(str==NULL){ 340 con->http_status = 400; 341 con->file_finished = 1; 342 return HANDLER_FINISHED; 343 } 344 345 if(con->request.http_method == HTTP_METHOD_POST){ 346 347 char *post_data; 348 if( parse_postdata_from_chunkqueue(srv, con, con->request_content_queue, &post_data) == 0 ){ 349 350 if(post_data!=NULL){ 351 Cdbg(DBE, "post_data=%s", post_data); 352 353 char* action = get_url_param_ualue(post_data, "action"); 354 355 if(strcmp(action, "register")==0){ 356 char* token = get_url_param_ualue(post_data, "token"); 357 char* username = get_url_param_ualue(post_data, "username"); 358 char* password = get_url_param_ualue(post_data, "password"); 359 char* security_code = get_url_param_ualue(post_data, "security_code"); 360 361 update_invite_t ret = update_account_invite(token, username, password, security_code); 362 363 if(post_data!=NULL) free(post_data); 364 if(action!=NULL) free(action); 365 if(token!=NULL) free(token); 366 if(username!=NULL) free(username); 367 if(password!=NULL) free(password); 368 if(security_code!=NULL) free(security_code); 369 370 if(ret == INVITE_FINISHED){ 371 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text")); 372 b = buffer_init(); 373 buffer_append_string_len(b, CONST_STR_LEN("OK")); 374 chunkqueue_append_buffer(con->write_queue, b); 375 buffer_free(b); 376 con->http_status = 200; 377 con->file_finished = 1; 378 return HANDLER_FINISHED; 379 } 380 else if(ret == INVITE_SECURITY_CODE_INVALID){ 381 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text")); 382 b = buffer_init(); 383 buffer_append_string_len(b, CONST_STR_LEN("SECURITY_CODE_INVALID")); 384 chunkqueue_append_buffer(con->write_queue, b); 385 buffer_free(b); 386 con->http_status = 200; 387 con->file_finished = 1; 388 return HANDLER_FINISHED; 389 } 390 else if(ret == INVITE_ACCOUNT_EXISTED){ 391 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text")); 392 b = buffer_init(); 393 buffer_append_string_len(b, CONST_STR_LEN("ACCOUNT_EXISTED")); 394 chunkqueue_append_buffer(con->write_queue, b); 395 buffer_free(b); 396 con->http_status = 200; 397 con->file_finished = 1; 398 return HANDLER_FINISHED; 399 } 400 else if(ret == INVITE_TOKEN_INVALID){ 401 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text")); 402 b = buffer_init(); 403 buffer_append_string_len(b, CONST_STR_LEN("TOKEN_INVALID")); 404 chunkqueue_append_buffer(con->write_queue, b); 405 buffer_free(b); 406 con->http_status = 200; 407 con->file_finished = 1; 408 return HANDLER_FINISHED; 409 } 410 else{ 411 con->http_status = 411; 412 con->file_finished = 1; 413 return HANDLER_FINISHED; 414 } 415 } 416 else if(strcmp(action, "get_invite_info")==0){ 417 418 int need_security_code = 0; 419 buffer* buffer_product_id = NULL; 420 buffer* buffer_device_id = NULL; 421 int auth_type = 0; 422 char* token = get_url_param_ualue(post_data, "token"); 423 int bTokenExist = 0; 424 425 Cdbg(DBE, "token=%s", token); 426 427 b = buffer_init(); 428 429 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("application/json")); 430 431 if (token==NULL) { 432 //- result 433 buffer_append_string_len(b, CONST_STR_LEN("{")); 434 buffer_append_string_len(b, CONST_STR_LEN("\"result\":\"TOKEN_INVALID\"")); 435 buffer_append_string_len(b, CONST_STR_LEN("}")); 436 437 if(action!=NULL) free(action); 438 if(post_data!=NULL) free(post_data); 439 440 chunkqueue_append_buffer(con->write_queue, b); 441 buffer_free(b); 442 443 con->http_status = 200; 444 con->file_finished = 1; 445 return HANDLER_FINISHED; 446 } 447 448 aicloud_acc_invite_info_t *c; 449 for (c = aicloud_acc_invite_info_list; c; c = c->next) { 450 if(buffer_is_equal_string(c->token, token, strlen(token))){ 451 bTokenExist = 1; 452 break; 453 } 454 } 455 456 if(bTokenExist==0){ 457 //- result 458 buffer_append_string_len(b, CONST_STR_LEN("{")); 459 buffer_append_string_len(b, CONST_STR_LEN("\"result\":\"TOKEN_INVALID\"")); 460 buffer_append_string_len(b, CONST_STR_LEN("}")); 461 462 if(action!=NULL) free(action); 463 if(post_data!=NULL) free(post_data); 464 465 chunkqueue_append_buffer(con->write_queue, b); 466 buffer_free(b); 467 468 con->http_status = 200; 469 con->file_finished = 1; 470 return HANDLER_FINISHED; 471 } 472 473 if( buffer_is_empty(c->security_code) || 474 strcmp(c->security_code->ptr, "none")==0 || 475 strcmp(c->security_code->ptr, "")==0 ){ 476 need_security_code = 0; 477 } 478 else{ 479 need_security_code = 1; 480 } 481 482 if(action!=NULL) free(action); 483 if(post_data!=NULL) free(post_data); 484 if(token!=NULL) free(token); 485 486 //- result 487 buffer_append_string_len(b, CONST_STR_LEN("{")); 488 buffer_append_string_len(b, CONST_STR_LEN("\"result\":\"OK\"")); 489 buffer_append_string_len(b, CONST_STR_LEN(",")); 490 491 buffer_append_string_len(b, CONST_STR_LEN("\"data\": {")); 492 493 //- product id 494 buffer_append_string_len(b, CONST_STR_LEN("\"productid\":\"")); 495 buffer_append_string_buffer(b, c->productid); 496 buffer_append_string_len(b, CONST_STR_LEN("\"")); 497 buffer_append_string_len(b, CONST_STR_LEN(",")); 498 buffer_free(buffer_product_id); 499 500 //- device id 501 buffer_append_string_len(b, CONST_STR_LEN("\"deviceid\":\"")); 502 buffer_append_string_buffer(b, c->deviceid); 503 buffer_append_string_len(b, CONST_STR_LEN("\"")); 504 buffer_append_string_len(b, CONST_STR_LEN(",")); 505 buffer_free(buffer_device_id); 506 507 //- security code needed 508 buffer_append_string_len(b, CONST_STR_LEN("\"need_security_code\":\"")); 509 if(need_security_code==1) 510 buffer_append_string_len(b, CONST_STR_LEN("1")); 511 else 512 buffer_append_string_len(b, CONST_STR_LEN("0")); 513 buffer_append_string_len(b, CONST_STR_LEN("\"")); 514 buffer_append_string_len(b, CONST_STR_LEN(",")); 515 516 //- auth type: 0:aicloud, 1:facebook, 2:google 517 buffer_append_string_len(b, CONST_STR_LEN("\"auth_type\":\"")); 518 char c_auth_type[2] = "\0"; 519 sprintf(c_auth_type, "%d", c->auth_type); 520 buffer_append_string_len(b, c_auth_type, strlen(c_auth_type)); 521 buffer_append_string_len(b, CONST_STR_LEN("\"")); 522 523 buffer_append_string_len(b, CONST_STR_LEN("}")); 524 525 buffer_append_string_len(b, CONST_STR_LEN("}")); 526 527 chunkqueue_append_buffer(con->write_queue, b); 528 buffer_free(b); 529 530 con->http_status = 200; 531 con->file_finished = 1; 532 return HANDLER_FINISHED; 533 } 534 535 free(post_data); 536 free(action); 537 538 } 539 540 } 541 542 con->http_status = 501; 543 con->file_finished = 1; 544 return HANDLER_FINISHED; 545 546 } 547 548 buffer *out; 549 int is_valid_token = 0; 550 buffer* buffer_token = buffer_init(); 551 buffer_copy_string_len(buffer_token, str, strlen(str)); 552 553 aicloud_acc_invite_info_t *c; 554 for (c = aicloud_acc_invite_info_list; c; c = c->next) { 555 if(buffer_is_equal(c->token, buffer_token)){ 556 if(c->status==0){ 557 is_valid_token = 1; 558 break; 559 } 560 } 561 } 562 563 con->file_finished = 1; 564 565 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html; charset=UTF-8")); 566 567 out = buffer_init(); 568 569 if(is_valid_token==1){ 570 buffer_append_string_len(out, CONST_STR_LEN("<input type=\"hidden\" id=\"invite_token\" value=\"")); 571 buffer_append_string_buffer(out, buffer_token); 572 buffer_append_string_len(out, CONST_STR_LEN("\">")); 573 574 con->http_status = 461; 575 } 576 else{ 577 //- redirect to aicloud url 578 //buffer_append_string_len(out, CONST_STR_LEN("<meta http-equiv=\"refresh\" content=\"0; url=/\" />")); 579 //con->http_status = 200; 580 con->http_status = 462; 581 } 582 583 buffer_free(buffer_token); 584 585 chunkqueue_append_buffer(con->write_queue, out); 586 buffer_free(out); 587 588 return HANDLER_FINISHED; 589} 590#ifndef APP_IPKG 591int mod_aicloud_invite_plugin_init(plugin *p); 592int mod_aicloud_invite_plugin_init(plugin *p) { 593 p->version = LIGHTTPD_VERSION_ID; 594 p->name = buffer_init_string("aicloud_invite"); 595 596 p->init = mod_aicloud_invite_init; 597 p->set_defaults = mod_aicloud_invite_set_defaults; 598 p->handle_physical = mod_aicloud_invite_physical_handler; 599 p->cleanup = mod_aicloud_invite_free; 600 601 p->data = NULL; 602 603 return 0; 604} 605#else 606int aicloud_mod_aicloud_invite_plugin_init(plugin *p); 607int aicloud_mod_aicloud_invite_plugin_init(plugin *p) { 608 p->version = LIGHTTPD_VERSION_ID; 609 p->name = buffer_init_string("aicloud_invite"); 610 611 p->init = mod_aicloud_invite_init; 612 p->set_defaults = mod_aicloud_invite_set_defaults; 613 p->handle_physical = mod_aicloud_invite_physical_handler; 614 p->cleanup = mod_aicloud_invite_free; 615 616 p->data = NULL; 617 618 return 0; 619} 620#endif 621