1#include "base.h" 2#include "log.h" 3#include "buffer.h" 4#include "response.h" 5 6#include "plugin.h" 7 8#include "stream.h" 9#include "stat_cache.h" 10 11#include "sys-mmap.h" 12 13#include <sys/types.h> 14#include <sys/stat.h> 15#include <ctype.h> 16#include <stdlib.h> 17#include <string.h> 18#include <errno.h> 19#include <fcntl.h> 20#include <stdio.h> 21#include <assert.h> 22 23#include <unistd.h> 24#include <dirent.h> 25#include <dlinklist.h> 26//#include <sys/socket.h> 27 28//#define USE_LIBEXIF 29#ifdef USE_LIBEXIF 30#include <libexif/exif-loader.h> 31#endif 32 33#if EMBEDDED_EANBLE 34#ifndef APP_IPKG 35#include "disk_share.h" 36#endif 37#endif 38 39#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) 40#define USE_PROPPATCH 41#define USE_MINIDLNA_DB 42#include <libxml/tree.h> 43#include <libxml/parser.h> 44#include <sqlite3.h> 45#endif 46 47#include <stdarg.h> 48 49#include <curl/curl.h> 50#include <openssl/md5.h> 51 52//#include "sql.h" 53/* 54#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_UUID_H) 55#define USE_LOCKS 56#include <uuid/uuid.h> 57#endif 58*/ 59 60#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) 61#define USE_LOCKS 62#endif 63 64#define MUSIC_ID "1" 65#define MUSIC_ALL_ID "1$4" 66#define MUSIC_GENRE_ID "1$5" 67#define MUSIC_ARTIST_ID "1$6" 68#define MUSIC_ALBUM_ID "1$7" 69#define MUSIC_PLIST_ID "1$F" 70#define MUSIC_DIR_ID "1$14" 71#define MUSIC_CONTRIB_ARTIST_ID "1$100" 72#define MUSIC_ALBUM_ARTIST_ID "1$107" 73#define MUSIC_COMPOSER_ID "1$108" 74#define MUSIC_RATING_ID "1$101" 75 76#define VIDEO_ID "2" 77#define VIDEO_ALL_ID "2$8" 78#define VIDEO_GENRE_ID "2$9" 79#define VIDEO_ACTOR_ID "2$A" 80#define VIDEO_SERIES_ID "2$E" 81#define VIDEO_PLIST_ID "2$10" 82#define VIDEO_DIR_ID "2$15" 83#define VIDEO_RATING_ID "2$200" 84 85#define IMAGE_ID "3" 86#define IMAGE_ALL_ID "3$B" 87#define IMAGE_DATE_ID "3$C" 88#define IMAGE_ALBUM_ID "3$D" 89#define IMAGE_CAMERA_ID "3$D2" // PlaysForSure == Keyword 90#define IMAGE_PLIST_ID "3$11" 91#define IMAGE_DIR_ID "3$16" 92#define IMAGE_RATING_ID "3$300" 93 94/** 95 * this is a webdav for a lighttpd plugin 96 * 97 * at least a very basic one. 98 * - for now it is read-only and we only support PROPFIND 99 * 100 */ 101 102#define WEBDAV_FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH 103#define WEBDAV_DIR_MODE S_IRWXU | S_IRWXG | S_IRWXO 104 105#define DBG_ENABLE_MOD_SMBDAV 1 106#define DBE DBG_ENABLE_MOD_SMBDAV 107 108/* plugin config for all request/connections */ 109 110typedef struct { 111 unsigned short enabled; 112 unsigned short is_readonly; 113 unsigned short log_xml; 114 115 buffer *sqlite_db_name; 116 array *alias_url; 117#ifdef USE_PROPPATCH 118 sqlite3 *sql; 119 sqlite3_stmt *stmt_update_prop; 120 sqlite3_stmt *stmt_delete_prop; 121 sqlite3_stmt *stmt_select_prop; 122 sqlite3_stmt *stmt_select_propnames; 123 124 sqlite3_stmt *stmt_delete_uri; 125 sqlite3_stmt *stmt_move_uri; 126 sqlite3_stmt *stmt_copy_uri; 127 128 sqlite3_stmt *stmt_remove_lock; 129 sqlite3_stmt *stmt_create_lock; 130 sqlite3_stmt *stmt_read_lock; 131 sqlite3_stmt *stmt_read_lock_by_uri; 132 sqlite3_stmt *stmt_refresh_lock; 133#endif 134} plugin_config; 135 136typedef struct { 137 PLUGIN_DATA; 138 139 buffer *tmp_buf; 140 request_uri uri; 141 physical physical; 142 143 plugin_config **config_storage; 144 145 plugin_config conf; 146 147 //- 20130304 Sungmin add 148 buffer *minidlna_db_dir; 149 buffer *minidlna_db_file; 150 buffer *minidlna_media_dir; 151 buffer *mnt_path; 152 153} plugin_data; 154 155/* init the plugin data */ 156INIT_FUNC(mod_webdav_init) { 157 158 plugin_data *p; 159 160 p = calloc(1, sizeof(*p)); 161 162 p->tmp_buf = buffer_init(); 163 164 p->uri.scheme = buffer_init(); 165 p->uri.path_raw = buffer_init(); 166 p->uri.path = buffer_init(); 167 p->uri.authority = buffer_init(); 168 169 p->physical.path = buffer_init(); 170 p->physical.rel_path = buffer_init(); 171 p->physical.doc_root = buffer_init(); 172 p->physical.basedir = buffer_init(); 173 174 //- 20130304 Sungmin add 175 p->minidlna_db_dir = buffer_init(); 176 p->minidlna_db_file = buffer_init(); 177 p->minidlna_media_dir = buffer_init(); 178 p->mnt_path = buffer_init(); 179 180 return p; 181} 182 183/* detroy the plugin data */ 184FREE_FUNC(mod_webdav_free) { 185 plugin_data *p = p_d; 186 187 UNUSED(srv); 188 189 if (!p) return HANDLER_GO_ON; 190 191 if (p->config_storage) { 192 size_t i; 193 for (i = 0; i < srv->config_context->used; i++) { 194 plugin_config *s = p->config_storage[i]; 195 196 if (NULL == s) continue; 197 198 array_free(s->alias_url); 199 buffer_free(s->sqlite_db_name); 200#ifdef USE_PROPPATCH 201 if (s->sql) { 202 sqlite3_finalize(s->stmt_delete_prop); 203 sqlite3_finalize(s->stmt_delete_uri); 204 sqlite3_finalize(s->stmt_copy_uri); 205 sqlite3_finalize(s->stmt_move_uri); 206 sqlite3_finalize(s->stmt_update_prop); 207 sqlite3_finalize(s->stmt_select_prop); 208 sqlite3_finalize(s->stmt_select_propnames); 209 210 sqlite3_finalize(s->stmt_read_lock); 211 sqlite3_finalize(s->stmt_read_lock_by_uri); 212 sqlite3_finalize(s->stmt_create_lock); 213 sqlite3_finalize(s->stmt_remove_lock); 214 sqlite3_finalize(s->stmt_refresh_lock); 215 sqlite3_close(s->sql); 216 } 217#endif 218 free(s); 219 } 220 free(p->config_storage); 221 } 222 223 buffer_free(p->uri.scheme); 224 buffer_free(p->uri.path_raw); 225 buffer_free(p->uri.path); 226 buffer_free(p->uri.authority); 227 228 buffer_free(p->physical.path); 229 buffer_free(p->physical.rel_path); 230 buffer_free(p->physical.doc_root); 231 buffer_free(p->physical.basedir); 232 233 buffer_free(p->tmp_buf); 234 235 //- 20130304 Sungmin add 236 buffer_free(p->minidlna_db_dir); 237 buffer_free(p->minidlna_db_file); 238 buffer_free(p->minidlna_media_dir); 239 buffer_free(p->mnt_path); 240 241 free(p); 242 243 return HANDLER_GO_ON; 244} 245 246/* handle plugin config and check values */ 247 248SETDEFAULTS_FUNC(mod_webdav_set_defaults) { 249 250 plugin_data *p = p_d; 251 size_t i = 0; 252 253 config_values_t cv[] = { 254 { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ 255 { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ 256 { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ 257 { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ 258 { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ 259 260 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } 261 }; 262 263 if (!p) return HANDLER_ERROR; 264 265 p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *)); 266 267 for (i = 0; i < srv->config_context->used; i++) { 268 data_config const* config = (data_config const*)srv->config_context->data[i]; 269 plugin_config *s; 270 271 s = calloc(1, sizeof(plugin_config)); 272 s->sqlite_db_name = buffer_init(); 273 s->alias_url = array_init(); 274 275 cv[0].destination = &(s->enabled); 276 cv[1].destination = &(s->is_readonly); 277 cv[2].destination = s->sqlite_db_name; 278 cv[3].destination = &(s->log_xml); 279 cv[4].destination = s->alias_url; 280 281 p->config_storage[i] = s; 282 283 if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) { 284 return HANDLER_ERROR; 285 } 286 287#if EMBEDDED_EANBLE 288 char *usbdiskname = nvram_get_productid(); 289#else 290 char *usbdiskname = "usbdisk"; 291#endif 292 293 for (size_t j = 0; j < s->alias_url->used; j++) { 294 data_string *ds = (data_string *)s->alias_url->data[j]; 295 if(strstr(ds->key->ptr, usbdiskname)!=NULL){ 296 buffer_copy_buffer(p->mnt_path, ds->value); 297 298 if(strcmp( p->mnt_path->ptr + (p->mnt_path->used -1 ), "/" )!=0) 299 buffer_append_string(p->mnt_path, "/"); 300 } 301 } 302#if EMBEDDED_EANBLE 303#ifdef APP_IPKG 304 free(usbdiskname); 305#endif 306#endif 307 308 if (!buffer_string_is_empty(s->sqlite_db_name)) { 309#ifdef USE_PROPPATCH 310 const char *next_stmt; 311 char *err; 312 313 if (SQLITE_OK != sqlite3_open(s->sqlite_db_name->ptr, &(s->sql))) { 314 log_error_write(srv, __FILE__, __LINE__, "sbs", "sqlite3_open failed for", 315 s->sqlite_db_name, 316 sqlite3_errmsg(s->sql)); 317 return HANDLER_ERROR; 318 } 319 320 if (SQLITE_OK != sqlite3_exec(s->sql, 321 "CREATE TABLE properties (" 322 " resource TEXT NOT NULL," 323 " prop TEXT NOT NULL," 324 " ns TEXT NOT NULL," 325 " value TEXT NOT NULL," 326 " PRIMARY KEY(resource, prop, ns))", 327 NULL, NULL, &err)) { 328 329 if (0 != strcmp(err, "table properties already exists")) { 330 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err); 331 sqlite3_free(err); 332 333 return HANDLER_ERROR; 334 } 335 sqlite3_free(err); 336 } 337 338 if (SQLITE_OK != sqlite3_prepare(s->sql, 339 CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 340 &(s->stmt_select_prop), &next_stmt)) { 341 /* prepare failed */ 342 343 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql)); 344 return HANDLER_ERROR; 345 } 346 347 if (SQLITE_OK != sqlite3_prepare(s->sql, 348 CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"), 349 &(s->stmt_select_propnames), &next_stmt)) { 350 /* prepare failed */ 351 352 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql)); 353 return HANDLER_ERROR; 354 } 355 356 357 if (SQLITE_OK != sqlite3_prepare(s->sql, 358 CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"), 359 &(s->stmt_update_prop), &next_stmt)) { 360 /* prepare failed */ 361 362 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql)); 363 return HANDLER_ERROR; 364 } 365 366 if (SQLITE_OK != sqlite3_prepare(s->sql, 367 CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"), 368 &(s->stmt_delete_prop), &next_stmt)) { 369 /* prepare failed */ 370 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 371 372 return HANDLER_ERROR; 373 } 374 375 if (SQLITE_OK != sqlite3_prepare(s->sql, 376 CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"), 377 &(s->stmt_delete_uri), &next_stmt)) { 378 /* prepare failed */ 379 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 380 381 return HANDLER_ERROR; 382 } 383 384 if (SQLITE_OK != sqlite3_prepare(s->sql, 385 CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"), 386 &(s->stmt_copy_uri), &next_stmt)) { 387 /* prepare failed */ 388 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 389 390 return HANDLER_ERROR; 391 } 392 393 if (SQLITE_OK != sqlite3_prepare(s->sql, 394 CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"), 395 &(s->stmt_move_uri), &next_stmt)) { 396 /* prepare failed */ 397 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 398 399 return HANDLER_ERROR; 400 } 401 402 /* LOCKS */ 403 404 if (SQLITE_OK != sqlite3_exec(s->sql, 405 "CREATE TABLE locks (" 406 " locktoken TEXT NOT NULL," 407 " resource TEXT NOT NULL," 408 " lockscope TEXT NOT NULL," 409 " locktype TEXT NOT NULL," 410 " owner TEXT NOT NULL," 411 " depth INT NOT NULL," 412 " timeout TIMESTAMP NOT NULL," 413 " PRIMARY KEY(locktoken))", 414 NULL, NULL, &err)) { 415 416 if (0 != strcmp(err, "table locks already exists")) { 417 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err); 418 sqlite3_free(err); 419 420 return HANDLER_ERROR; 421 } 422 sqlite3_free(err); 423 } 424 425 if (SQLITE_OK != sqlite3_prepare(s->sql, 426 CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"), 427 &(s->stmt_create_lock), &next_stmt)) { 428 /* prepare failed */ 429 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 430 431 return HANDLER_ERROR; 432 } 433 434 if (SQLITE_OK != sqlite3_prepare(s->sql, 435 CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"), 436 &(s->stmt_remove_lock), &next_stmt)) { 437 /* prepare failed */ 438 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 439 440 return HANDLER_ERROR; 441 } 442 443 if (SQLITE_OK != sqlite3_prepare(s->sql, 444 CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"), 445 &(s->stmt_read_lock), &next_stmt)) { 446 /* prepare failed */ 447 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 448 449 return HANDLER_ERROR; 450 } 451 452 if (SQLITE_OK != sqlite3_prepare(s->sql, 453 CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"), 454 &(s->stmt_read_lock_by_uri), &next_stmt)) { 455 /* prepare failed */ 456 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 457 458 return HANDLER_ERROR; 459 } 460 461 if (SQLITE_OK != sqlite3_prepare(s->sql, 462 CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"), 463 &(s->stmt_refresh_lock), &next_stmt)) { 464 /* prepare failed */ 465 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql)); 466 467 return HANDLER_ERROR; 468 } 469 470 471#else 472 log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props"); 473 return HANDLER_ERROR; 474#endif 475 } 476 } 477 478 return HANDLER_GO_ON; 479} 480 481#define PATCH_OPTION(x) \ 482 p->conf.x = s->x; 483static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) { 484 size_t i, j; 485 plugin_config *s = p->config_storage[0]; 486 487 PATCH_OPTION(enabled); 488 PATCH_OPTION(is_readonly); 489 PATCH_OPTION(log_xml); 490 491#ifdef USE_PROPPATCH 492 PATCH_OPTION(sql); 493 PATCH_OPTION(stmt_update_prop); 494 PATCH_OPTION(stmt_delete_prop); 495 PATCH_OPTION(stmt_select_prop); 496 PATCH_OPTION(stmt_select_propnames); 497 498 PATCH_OPTION(stmt_delete_uri); 499 PATCH_OPTION(stmt_move_uri); 500 PATCH_OPTION(stmt_copy_uri); 501 502 PATCH_OPTION(stmt_remove_lock); 503 PATCH_OPTION(stmt_refresh_lock); 504 PATCH_OPTION(stmt_create_lock); 505 PATCH_OPTION(stmt_read_lock); 506 PATCH_OPTION(stmt_read_lock_by_uri); 507#endif 508 /* skip the first, the global context */ 509 for (i = 1; i < srv->config_context->used; i++) { 510 data_config *dc = (data_config *)srv->config_context->data[i]; 511 s = p->config_storage[i]; 512 513 /* condition didn't match */ 514 if (!config_check_cond(srv, con, dc)) continue; 515 516 /* merge config */ 517 for (j = 0; j < dc->value->used; j++) { 518 data_unset *du = dc->value->data[j]; 519 520 if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) { 521 PATCH_OPTION(enabled); 522 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) { 523 PATCH_OPTION(is_readonly); 524 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) { 525 PATCH_OPTION(log_xml); 526 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) { 527#ifdef USE_PROPPATCH 528 PATCH_OPTION(sql); 529 PATCH_OPTION(stmt_update_prop); 530 PATCH_OPTION(stmt_delete_prop); 531 PATCH_OPTION(stmt_select_prop); 532 PATCH_OPTION(stmt_select_propnames); 533 534 PATCH_OPTION(stmt_delete_uri); 535 PATCH_OPTION(stmt_move_uri); 536 PATCH_OPTION(stmt_copy_uri); 537 538 PATCH_OPTION(stmt_remove_lock); 539 PATCH_OPTION(stmt_refresh_lock); 540 PATCH_OPTION(stmt_create_lock); 541 PATCH_OPTION(stmt_read_lock); 542 PATCH_OPTION(stmt_read_lock_by_uri); 543#endif 544 } 545 } 546 } 547 548 return 0; 549} 550 551URIHANDLER_FUNC(mod_webdav_uri_handler) { 552 plugin_data *p = p_d; 553 554 UNUSED(srv); 555 556 if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON; 557 558 mod_webdav_patch_connection(srv, con, p); 559 560 if (!p->conf.enabled) return HANDLER_GO_ON; 561 562 switch (con->request.http_method) { 563 case HTTP_METHOD_OPTIONS: 564 /* we fake a little bit but it makes MS W2k happy and it let's us mount the volume */ 565 response_header_overwrite(srv, con, CONST_STR_LEN("DAV"), CONST_STR_LEN("1,2")); 566 response_header_overwrite(srv, con, CONST_STR_LEN("MS-Author-Via"), CONST_STR_LEN("DAV")); 567 568 if (p->conf.is_readonly) { 569 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND")); 570 } else { 571 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK")); 572 } 573 break; 574 default: 575 break; 576 } 577 578 /* not found */ 579 return HANDLER_GO_ON; 580} 581 582static size_t curl_write_callback_func(void *ptr, size_t size, size_t count, void *stream) 583{ 584 /* ptr - your string variable. 585 stream - data chuck you received */ 586 char **response_ptr = (char**)stream; 587 588 /* assuming the response is a string */ 589 *response_ptr = strndup(ptr, (size_t)(size *count)); 590 591 //printf("%.*s", size, (char*)stream)); 592 //Cdbg(1, "callback_func.... %s", (char*)ptr); 593} 594#if 0 595 596/* md5sum: 597 * Concatenates a series of strings together then generates an md5 598 * message digest. Writes the result directly into 'output', which 599 * MUST be large enough to accept the result. (Size == 600 * 128 + null terminator.) 601 */ 602char secret[100] = "804b51d14d840d6e"; 603/* sprint_hex: 604 * print a long hex value into a string buffer. This function will 605 * write 'len' bytes of data from 'char_buf' into 2*len bytes of space 606 * in 'output'. (Each hex value is 4 bytes.) Space in output must be 607 * pre-allocated. */ 608void sprint_hex(char* output, unsigned char* char_buf, int len) 609{ 610 int i; 611 for (i=0; i < len; i++) { 612 sprintf(output + i*2, "%02x", char_buf[i]); 613 } 614} 615 616void md5sum(char* output, int counter, ...) 617{ 618 va_list argp; 619 unsigned char temp[MD5_DIGEST_LENGTH]; 620 char* md5_string; 621 int full_len; 622 int i, str_len; 623 int buffer_size = 10; 624 625 md5_string = (char*)malloc(buffer_size); 626 md5_string[0] = '\0'; 627 628 full_len = 0; 629 va_start(argp, secret); 630 for (i = 0; i < counter; i++) { 631 char* string = va_arg(argp, char*); 632 int len = strlen(string); 633 634 /* If the buffer is not large enough, expand until it is. */ 635 while (len + full_len > buffer_size - 1) { 636 buffer_size += buffer_size; 637 md5_string = realloc(md5_string, buffer_size); 638 } 639 640 strncat(md5_string, string, len); 641 642 full_len += len; 643 md5_string[full_len] = '\0'; 644 } 645 va_end(argp); 646 647 str_len = strlen(md5_string); 648 MD5((const unsigned char*)md5_string, (unsigned int)str_len, temp); 649 650 free(md5_string); 651 652 sprint_hex(output, temp, MD5_DIGEST_LENGTH); 653 output[129] = '\0'; 654} 655#endif 656 657static int get_minidlna_db_path(plugin_data *p){ 658 659 if(is_dms_enabled()==0){ 660 return 0; 661 } 662 663 //- 20130603 JerryLin add 664 int bOpenConfigFle = 1; 665#if EMBEDDED_EANBLE 666 char* db_dir = nvram_get_dms_dbcwd(); 667 if(db_dir){ 668 buffer_copy_string_len(p->minidlna_db_dir, db_dir, strlen(db_dir)); 669 buffer_copy_string_len(p->minidlna_db_file, db_dir, strlen(db_dir)); 670 buffer_append_string(p->minidlna_db_file, "/files.db"); 671 bOpenConfigFle = 0; 672 } 673 674 char* media_dir = nvram_get_dms_dir(); 675 if(media_dir){ 676 buffer_copy_string_len(p->minidlna_media_dir, media_dir, strlen(media_dir)); 677 bOpenConfigFle = 0; 678 } 679#endif 680 if(bOpenConfigFle==1){ 681 FILE* fp2; 682 char line[128]; 683 char* minidla_config_file = NULL; 684 char* minidla_config_file_tmp = "/etc/minidlna.conf"; 685 if(access(minidla_config_file_tmp,R_OK) == 0) 686 minidla_config_file = "/etc/minidlna.conf"; 687 else 688 minidla_config_file = "/opt/etc/minidlna.conf"; 689 690 if((fp2 = fopen(minidla_config_file, "r")) != NULL){ 691 memset(line, 0, sizeof(line)); 692 while(fgets(line, 128, fp2) != NULL){ 693 if(strncmp(line, "db_dir=", 7)==0){ 694 char tmp[100] = "\0"; 695 strncpy(tmp, line + 7, strlen(line)-7); 696 tmp[strlen(tmp)-1]='\0'; 697 698 buffer_copy_string_len(p->minidlna_db_dir, tmp, strlen(tmp) ); 699 700 strcat(tmp, "/files.db"); 701 buffer_copy_string_len(p->minidlna_db_file, tmp, strlen(tmp) ); 702 } 703 else if(strncmp(line, "media_dir=", 10)==0){ 704 char tmp[100] = "\0"; 705 strncpy(tmp, line + 10, strlen(line)-10); 706 tmp[strlen(tmp)-1]='\0'; 707 708 buffer_copy_string_len(p->minidlna_media_dir, tmp, strlen(tmp) ); 709 } 710 } 711 fclose(fp2); 712 } 713 } 714 715#if EMBEDDED_EANBLE 716#ifdef APP_IPKG 717 if(db_dir) 718 free(db_dir); 719 720 if(media_dir) 721 free(media_dir); 722#endif 723#endif 724 //Cdbg(DBE, ".............................minidlna_db_dir=%s", p->minidlna_db_dir->ptr); 725 //Cdbg(DBE, ".............................minidlna_db_file=%s", p->minidlna_db_file->ptr); 726 //Cdbg(DBE, ".............................minidlna_media_dir=%s", p->minidlna_media_dir->ptr); 727 728} 729 730static int get_thumb_image(char* path, plugin_data *p, unsigned char **out){ 731 if(is_dms_enabled()==0){ 732 return 0; 733 } 734 735#if EMBEDDED_EANBLE 736 char* thumb_dir = (char *)malloc(PATH_MAX); 737 if(!thumb_dir) return 0; 738 739 if (buffer_is_empty(p->minidlna_db_dir)) 740 get_minidlna_db_path(p); 741 742 strcpy(thumb_dir, p->minidlna_db_dir->ptr); 743 strcat(thumb_dir, "/art_cache/tmp"); 744 745 char* filename = NULL; 746 extract_filename(path, &filename); 747 const char *dot = strrchr(filename, '.'); 748 int len = dot - filename; 749 750 char* filepath = NULL; 751 extract_filepath(path, &filepath); 752 753 strcat(thumb_dir, filepath); 754 strncat(thumb_dir, filename, len); 755 strcat(thumb_dir, ".jpg"); 756 757 free(filename); 758 free(filepath); 759#else 760 char* db_dir = "/var/lib/minidlna/"; 761 char* thumb_dir = (char *)malloc(PATH_MAX); 762 763 if(!thumb_dir){ 764 return 0; 765 } 766 strcpy(thumb_dir, db_dir); 767 strcat(thumb_dir, "art_cache"); 768 769 char* filename = NULL; 770 extract_filename(path, &filename); 771 const char *dot = strrchr(filename, '.'); 772 int index = dot - filename; 773 //Cdbg(DBE,"dot = %s, index=%d", dot, index); 774 775 char* filepath = NULL; 776 extract_filepath(path, &filepath); 777 778 Cdbg(DBE,"filepath=%s, filename=%s", filepath, filename); 779 780 strcat(thumb_dir, filepath); 781 strncat(thumb_dir, filename, index); 782 strcat(thumb_dir, ".jpg"); 783 784 free(filename); 785 free(filepath); 786 787#endif 788 Cdbg(DBE,"thumb_dir=%s", thumb_dir); 789 790 int result = 0; 791 792 FILE* fp = fopen(thumb_dir, "rb"); 793 794 if(fp!=NULL){ 795 Cdbg(DBE, "success to open thumb_dir=%s", thumb_dir); 796 //Get file length 797 fseek(fp, 0, SEEK_END); 798 int fileLen = ftell(fp); 799 fseek(fp, 0, SEEK_SET); 800 801 char* buffer = (char *)malloc(fileLen+1); 802 if(buffer){ 803 fread( buffer, fileLen, sizeof(unsigned char), fp ); 804 805 unsigned char* tmp = ldb_base64_encode(buffer, fileLen); 806 uint32 olen = strlen(tmp) + 1; 807 *out = (char*)malloc(olen); 808 memcpy(*out, tmp, olen); 809 810 free(tmp); 811 free(buffer); 812 813 fclose(fp); 814 815 result = 1; 816 } 817 } 818 819 free(thumb_dir); 820 return result; 821} 822 823static int get_album_cover_image(sqlite3 *sql_minidlna, sqlite_int64 plAlbumArt, unsigned char **out){ 824 if(is_dms_enabled()==0){ 825 return 0; 826 } 827 828 if(plAlbumArt<=0){ 829 return 0; 830 } 831 832 int rows2; 833 char **result2; 834 char* base64_image = NULL; 835 char sql_query[2048] = "\0"; 836 837 sprintf(sql_query, "SELECT PATH FROM ALBUM_ART WHERE ID = '%lld'", plAlbumArt ); 838 if( sql_get_table(sql_minidlna, sql_query, &result2, &rows2, NULL) == SQLITE_OK ){ 839 //Cdbg(DBE, "get_album_cover_image, album cover path=%s", result2[1]); 840 841 char* album_cover_file = result2[1]; 842 843 FILE* fp = fopen(album_cover_file, "rb"); 844 845 if(fp!=NULL){ 846 //Get file length 847 fseek(fp, 0, SEEK_END); 848 int fileLen = ftell(fp); 849 fseek(fp, 0, SEEK_SET); 850 851 char* buffer = (char *)malloc(fileLen+1); 852 if(!buffer){ 853 return 0; 854 } 855 char* aa = get_filename_ext(album_cover_file); 856 int len = strlen(aa)+1; 857 char* file_ext = (char*)malloc(len); 858 memset(file_ext,'\0', len); 859 strcpy(file_ext, aa); 860 for (int i = 0; file_ext[i]; i++) 861 file_ext[i] = tolower(file_ext[i]); 862 863 fread( buffer, fileLen, sizeof(unsigned char), fp ); 864 865 unsigned char* tmp = ldb_base64_encode(buffer, fileLen); 866 uint32 olen = strlen(tmp) + 1; 867 *out = (char*)malloc(olen); 868 memcpy(*out, tmp, olen); 869 870 free(tmp); 871 free(file_ext); 872 free(buffer); 873 874 fclose(fp); 875 } 876 877 } 878 sqlite3_free_table(result2); 879 880 return 1; 881} 882 883static int webdav_gen_prop_tag(server *srv, connection *con, 884 char *prop_name, 885 char *prop_ns, 886 char *value, 887 buffer *b) { 888 889 UNUSED(srv); 890 UNUSED(con); 891 892 if (value) { 893 buffer_append_string_len(b,CONST_STR_LEN("<")); 894 buffer_append_string(b, prop_name); 895 buffer_append_string_len(b, CONST_STR_LEN(" xmlns=\"")); 896 buffer_append_string(b, prop_ns); 897 buffer_append_string_len(b, CONST_STR_LEN("\">")); 898 899 buffer_append_string(b, value); 900 901 buffer_append_string_len(b,CONST_STR_LEN("</")); 902 buffer_append_string(b, prop_name); 903 buffer_append_string_len(b, CONST_STR_LEN(">")); 904 } else { 905 buffer_append_string_len(b,CONST_STR_LEN("<")); 906 buffer_append_string(b, prop_name); 907 buffer_append_string_len(b, CONST_STR_LEN(" xmlns=\"")); 908 buffer_append_string(b, prop_ns); 909 buffer_append_string_len(b, CONST_STR_LEN("\"/>")); 910 } 911 912 return 0; 913} 914 915 916static int webdav_gen_response_status_tag(server *srv, connection *con, physical *dst, int status, buffer *b) { 917 UNUSED(srv); 918 919 buffer_append_string_len(b,CONST_STR_LEN("<D:response xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n")); 920 921 buffer_append_string_len(b,CONST_STR_LEN("<D:href>\n")); 922 buffer_append_string_buffer(b, dst->rel_path); 923 buffer_append_string_len(b,CONST_STR_LEN("</D:href>\n")); 924 buffer_append_string_len(b,CONST_STR_LEN("<D:status>\n")); 925 926 if (con->request.http_version == HTTP_VERSION_1_1) { 927 buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1 ")); 928 } else { 929 buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.0 ")); 930 } 931 buffer_append_int(b, status); 932 buffer_append_string_len(b, CONST_STR_LEN(" ")); 933 buffer_append_string(b, get_http_status_name(status)); 934 935 buffer_append_string_len(b,CONST_STR_LEN("</D:status>\n")); 936 buffer_append_string_len(b,CONST_STR_LEN("</D:response>\n")); 937 938 return 0; 939} 940 941static int webdav_delete_file(server *srv, connection *con, plugin_data *p, physical *dst, buffer *b) { 942 int status = 0; 943 944 /* try to unlink it */ 945 if (-1 == unlink(dst->path->ptr)) { 946 switch(errno) { 947 case EACCES: 948 case EPERM: 949 /* 403 */ 950 status = 403; 951 break; 952 default: 953 status = 501; 954 break; 955 } 956 webdav_gen_response_status_tag(srv, con, dst, status, b); 957 } else { 958#ifdef USE_PROPPATCH 959 sqlite3_stmt *stmt = p->conf.stmt_delete_uri; 960 961 if (!stmt) { 962 status = 403; 963 webdav_gen_response_status_tag(srv, con, dst, status, b); 964 } else { 965 sqlite3_reset(stmt); 966 967 /* bind the values to the insert */ 968 969 sqlite3_bind_text(stmt, 1, 970 CONST_BUF_LEN(dst->rel_path), 971 SQLITE_TRANSIENT); 972 973 if (SQLITE_DONE != sqlite3_step(stmt)) { 974 /* */ 975 } 976 } 977#else 978 UNUSED(p); 979#endif 980 } 981 982 return (status != 0); 983} 984 985static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physical *dst, buffer *b) { 986 DIR *dir; 987 int have_multi_status = 0; 988 physical d; 989 990 d.path = buffer_init(); 991 d.rel_path = buffer_init(); 992 993 if (NULL != (dir = opendir(dst->path->ptr))) { 994 struct dirent *de; 995 996 while(NULL != (de = readdir(dir))) { 997 struct stat st; 998 int status = 0; 999 1000 if ((de->d_name[0] == '.' && de->d_name[1] == '\0') || 1001 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) { 1002 continue; 1003 /* ignore the parent dir */ 1004 } 1005 1006 buffer_copy_buffer(d.path, dst->path); 1007 buffer_append_slash(d.path); 1008 buffer_append_string(d.path, de->d_name); 1009 1010 buffer_copy_buffer(d.rel_path, dst->rel_path); 1011 buffer_append_slash(d.rel_path); 1012 buffer_append_string(d.rel_path, de->d_name); 1013 1014 /* stat and unlink afterwards */ 1015 if (-1 == stat(d.path->ptr, &st)) { 1016 /* don't about it yet, rmdir will fail too */ 1017 } else if (S_ISDIR(st.st_mode)) { 1018 have_multi_status = webdav_delete_dir(srv, con, p, &d, b); 1019 1020 /* try to unlink it */ 1021 if (-1 == rmdir(d.path->ptr)) { 1022 switch(errno) { 1023 case EACCES: 1024 case EPERM: 1025 /* 403 */ 1026 status = 403; 1027 break; 1028 default: 1029 status = 501; 1030 break; 1031 } 1032 have_multi_status = 1; 1033 1034 webdav_gen_response_status_tag(srv, con, &d, status, b); 1035 } else { 1036#ifdef USE_PROPPATCH 1037 sqlite3_stmt *stmt = p->conf.stmt_delete_uri; 1038 1039 status = 0; 1040 1041 if (stmt) { 1042 sqlite3_reset(stmt); 1043 1044 /* bind the values to the insert */ 1045 1046 sqlite3_bind_text(stmt, 1, 1047 CONST_BUF_LEN(d.rel_path), 1048 SQLITE_TRANSIENT); 1049 1050 if (SQLITE_DONE != sqlite3_step(stmt)) { 1051 /* */ 1052 } 1053 } 1054#endif 1055 } 1056 } else { 1057 have_multi_status = webdav_delete_file(srv, con, p, &d, b); 1058 } 1059 } 1060 closedir(dir); 1061 1062 buffer_free(d.path); 1063 buffer_free(d.rel_path); 1064 } 1065 1066 return have_multi_status; 1067} 1068 1069static int webdav_copy_file(server *srv, connection *con, plugin_data *p, physical *src, physical *dst, int overwrite) { 1070 stream s; 1071 int status = 0, ofd; 1072 UNUSED(srv); 1073 UNUSED(con); 1074 1075 if (stream_open(&s, src->path)) { 1076 return 403; 1077 } 1078 1079 if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), WEBDAV_FILE_MODE))) { 1080 /* opening the destination failed for some reason */ 1081 switch(errno) { 1082 case EEXIST: 1083 status = 412; 1084 break; 1085 case EISDIR: 1086 status = 409; 1087 break; 1088 case ENOENT: 1089 /* at least one part in the middle wasn't existing */ 1090 status = 409; 1091 break; 1092 default: 1093 status = 403; 1094 break; 1095 } 1096 stream_close(&s); 1097 return status; 1098 } 1099 1100 if (-1 == write(ofd, s.start, s.size)) { 1101 switch(errno) { 1102 case ENOSPC: 1103 status = 507; 1104 break; 1105 default: 1106 status = 403; 1107 break; 1108 } 1109 } 1110 1111 stream_close(&s); 1112 close(ofd); 1113 1114#ifdef USE_PROPPATCH 1115 if (0 == status) { 1116 /* copy worked fine, copy connected properties */ 1117 sqlite3_stmt *stmt = p->conf.stmt_copy_uri; 1118 1119 if (stmt) { 1120 sqlite3_reset(stmt); 1121 1122 /* bind the values to the insert */ 1123 sqlite3_bind_text(stmt, 1, 1124 CONST_BUF_LEN(dst->rel_path), 1125 SQLITE_TRANSIENT); 1126 1127 sqlite3_bind_text(stmt, 2, 1128 CONST_BUF_LEN(src->rel_path), 1129 SQLITE_TRANSIENT); 1130 1131 if (SQLITE_DONE != sqlite3_step(stmt)) { 1132 /* */ 1133 } 1134 } 1135 } 1136#else 1137 UNUSED(p); 1138#endif 1139 return status; 1140} 1141 1142static int webdav_copy_dir(server *srv, connection *con, plugin_data *p, physical *src, physical *dst, int overwrite) { 1143 DIR *srcdir; 1144 int status = 0; 1145 1146 if (NULL != (srcdir = opendir(src->path->ptr))) { 1147 struct dirent *de; 1148 physical s, d; 1149 1150 s.path = buffer_init(); 1151 s.rel_path = buffer_init(); 1152 1153 d.path = buffer_init(); 1154 d.rel_path = buffer_init(); 1155 1156 while (NULL != (de = readdir(srcdir))) { 1157 struct stat st; 1158 1159 if ((de->d_name[0] == '.' && de->d_name[1] == '\0') 1160 || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) { 1161 continue; 1162 } 1163 1164 buffer_copy_buffer(s.path, src->path); 1165 buffer_append_slash(s.path); 1166 buffer_append_string(s.path, de->d_name); 1167 1168 buffer_copy_buffer(d.path, dst->path); 1169 buffer_append_slash(d.path); 1170 buffer_append_string(d.path, de->d_name); 1171 1172 buffer_copy_buffer(s.rel_path, src->rel_path); 1173 buffer_append_slash(s.rel_path); 1174 buffer_append_string(s.rel_path, de->d_name); 1175 1176 buffer_copy_buffer(d.rel_path, dst->rel_path); 1177 buffer_append_slash(d.rel_path); 1178 buffer_append_string(d.rel_path, de->d_name); 1179 1180 if (-1 == stat(s.path->ptr, &st)) { 1181 /* why ? */ 1182 } else if (S_ISDIR(st.st_mode)) { 1183 /* a directory */ 1184 if (-1 == mkdir(d.path->ptr, WEBDAV_DIR_MODE) && 1185 errno != EEXIST) { 1186 /* WTH ? */ 1187 } else { 1188#ifdef USE_PROPPATCH 1189 sqlite3_stmt *stmt = p->conf.stmt_copy_uri; 1190 1191 if (0 != (status = webdav_copy_dir(srv, con, p, &s, &d, overwrite))) { 1192 break; 1193 } 1194 /* directory is copied, copy the properties too */ 1195 1196 if (stmt) { 1197 sqlite3_reset(stmt); 1198 1199 /* bind the values to the insert */ 1200 sqlite3_bind_text(stmt, 1, 1201 CONST_BUF_LEN(dst->rel_path), 1202 SQLITE_TRANSIENT); 1203 1204 sqlite3_bind_text(stmt, 2, 1205 CONST_BUF_LEN(src->rel_path), 1206 SQLITE_TRANSIENT); 1207 1208 if (SQLITE_DONE != sqlite3_step(stmt)) { 1209 /* */ 1210 } 1211 } 1212#endif 1213 } 1214 } else if (S_ISREG(st.st_mode)) { 1215 /* a plain file */ 1216 if (0 != (status = webdav_copy_file(srv, con, p, &s, &d, overwrite))) { 1217 break; 1218 } 1219 } 1220 } 1221 1222 buffer_free(s.path); 1223 buffer_free(s.rel_path); 1224 buffer_free(d.path); 1225 buffer_free(d.rel_path); 1226 1227 closedir(srcdir); 1228 } 1229 1230 return status; 1231} 1232 1233static int webdav_get_live_property(server *srv, connection *con, plugin_data *p, physical *dst, char *prop_name, buffer *b) { 1234 stat_cache_entry *sce = NULL; 1235 int found = 0; 1236 1237 UNUSED(p); 1238 1239 if (HANDLER_ERROR != (stat_cache_get_entry(srv, con, dst->path, &sce))) { 1240 char ctime_buf[] = "2005-08-18T07:27:16Z"; 1241 char mtime_buf[] = "Thu, 18 Aug 2005 07:27:16 GMT"; 1242 size_t k; 1243 1244 if (0 == strcmp(prop_name, "resourcetype")) { 1245 if (S_ISDIR(sce->st.st_mode)) { 1246 buffer_append_string_len(b, CONST_STR_LEN("<D:resourcetype><D:collection/></D:resourcetype>")); 1247 found = 1; 1248 } 1249 } else if (0 == strcmp(prop_name, "getcontenttype")) { 1250 if (S_ISDIR(sce->st.st_mode)) { 1251 buffer_append_string_len(b, CONST_STR_LEN("<D:getcontenttype>httpd/unix-directory</D:getcontenttype>")); 1252 found = 1; 1253 } else if(S_ISREG(sce->st.st_mode)) { 1254 for (k = 0; k < con->conf.mimetypes->used; k++) { 1255 data_string *ds = (data_string *)con->conf.mimetypes->data[k]; 1256 1257 if (buffer_is_empty(ds->key)) continue; 1258 1259 if (buffer_is_equal_right_len(dst->path, ds->key, buffer_string_length(ds->key))) { 1260 buffer_append_string_len(b,CONST_STR_LEN("<D:getcontenttype>")); 1261 buffer_append_string_buffer(b, ds->value); 1262 buffer_append_string_len(b, CONST_STR_LEN("</D:getcontenttype>")); 1263 found = 1; 1264 1265 break; 1266 } 1267 } 1268 } 1269 } else if (0 == strcmp(prop_name, "creationdate")) { 1270 //buffer_append_string_len(b, CONST_STR_LEN("<D:creationdate ns0:dt=\"dateTime.tz\">")); 1271 buffer_append_string_len(b, CONST_STR_LEN("<D:creationdate>")); 1272 strftime(ctime_buf, sizeof(ctime_buf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&(sce->st.st_ctime))); 1273 buffer_append_string(b, ctime_buf); 1274 buffer_append_string_len(b, CONST_STR_LEN("</D:creationdate>")); 1275 found = 1; 1276 } else if (0 == strcmp(prop_name, "getlastmodified")) { 1277 //buffer_append_string_len(b,CONST_STR_LEN("<D:getlastmodified ns0:dt=\"dateTime.rfc1123\">")); 1278 buffer_append_string_len(b,CONST_STR_LEN("<D:getlastmodified>")); 1279 strftime(mtime_buf, sizeof(mtime_buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(sce->st.st_mtime))); 1280 //strftime(mtime_buf, sizeof(mtime_buf), "%Y/%m/%d %H:%M:%S", localtime(&(sce->st.st_mtime))); 1281 buffer_append_string(b, mtime_buf); 1282 buffer_append_string_len(b, CONST_STR_LEN("</D:getlastmodified>")); 1283 found = 1; 1284 } else if (0 == strcmp(prop_name, "getcontentlength")) { 1285 buffer_append_string_len(b,CONST_STR_LEN("<D:getcontentlength>")); 1286 buffer_append_int(b, sce->st.st_size); 1287 buffer_append_string_len(b, CONST_STR_LEN("</D:getcontentlength>")); 1288 found = 1; 1289 } else if (0 == strcmp(prop_name, "getcontentlanguage")) { 1290 buffer_append_string_len(b,CONST_STR_LEN("<D:getcontentlanguage>")); 1291 buffer_append_string_len(b, CONST_STR_LEN("en")); 1292 buffer_append_string_len(b, CONST_STR_LEN("</D:getcontentlanguage>")); 1293 found = 1; 1294 }else if (0 == strcmp(prop_name, "getmac")) { 1295 //- 20111124 Jerry add 1296 buffer_append_string_len(b,CONST_STR_LEN("<D:getmac>")); 1297 buffer_append_string_len(b, CONST_STR_LEN("</D:getmac>")); 1298 found = 1; 1299 }else if (0 == strcmp(prop_name, "getonline")) { 1300 //- 20111219 Jerry add 1301 buffer_append_string_len(b,CONST_STR_LEN("<D:getonline>")); 1302 buffer_append_string_len(b, CONST_STR_LEN("1")); 1303 buffer_append_string_len(b, CONST_STR_LEN("</D:getonline>")); 1304 found = 1; 1305 }else if (0 == strcmp(prop_name, "getuniqueid")) { 1306 //- 20120104 Jerry add 1307 buffer_append_string_len(b,CONST_STR_LEN("<D:getuniqueid>")); 1308 char* result; 1309 md5String(dst->rel_path->ptr, NULL, &result); 1310 buffer_append_string(b, result); 1311 free(result); 1312 buffer_append_string_len(b, CONST_STR_LEN("</D:getuniqueid>")); 1313 found = 1; 1314 }else if (0 == strcmp(prop_name, "getattr")) { 1315 //- 20120302 Jerry add 1316 buffer_append_string_len(b,CONST_STR_LEN("<D:getattr>")); 1317 1318 int permission = -1; 1319 #if EMBEDDED_EANBLE 1320 char* usbdisk_rel_sub_path = NULL; 1321 char* usbdisk_sub_share_folder = NULL; 1322 1323 smbc_parse_mnt_path(dst->path->ptr, 1324 p->mnt_path->ptr, 1325 p->mnt_path->used-1, 1326 &usbdisk_rel_sub_path, 1327 &usbdisk_sub_share_folder); 1328 1329 permission = smbc_get_usbdisk_permission(con->aidisk_username->ptr, usbdisk_rel_sub_path, usbdisk_sub_share_folder); 1330 1331 free(usbdisk_rel_sub_path); 1332 free(usbdisk_sub_share_folder); 1333 1334 buffer_append_string_len(b, CONST_STR_LEN("<D:readonly>")); 1335 if( permission == 3 ) 1336 buffer_append_string_len(b, CONST_STR_LEN("false")); 1337 else 1338 buffer_append_string_len(b, CONST_STR_LEN("true")); 1339 buffer_append_string_len(b, CONST_STR_LEN("</D:readonly>")); 1340 #else 1341 buffer_append_string_len(b, CONST_STR_LEN("<D:readonly>")); 1342 buffer_append_string_len(b, CONST_STR_LEN("true")); 1343 buffer_append_string_len(b, CONST_STR_LEN("</D:readonly>")); 1344 #endif 1345 1346 buffer_append_string_len(b, CONST_STR_LEN("<D:hidden>")); 1347 buffer_append_string_len(b, CONST_STR_LEN("false")); 1348 buffer_append_string_len(b, CONST_STR_LEN("</D:hidden>")); 1349 1350 buffer_append_string_len(b, CONST_STR_LEN("</D:getattr>")); 1351 1352 found = 1; 1353 } 1354 else if (0 == strcmp(prop_name, "gettype")) { 1355 //- 20120208 Jerry add 1356 buffer_append_string_len(b,CONST_STR_LEN("<D:gettype>")); 1357 buffer_append_string(b, "usbdisk"); 1358 buffer_append_string_len(b, CONST_STR_LEN("</D:gettype>")); 1359 found = 1; 1360 } 1361 else if (0 == strcmp(prop_name, "getuseragent")) { 1362 //- 20121205 Jerry add 1363 buffer_append_string_len(b,CONST_STR_LEN("<D:getuseragent>")); 1364 if(con->smb_info){ 1365 buffer_append_string_buffer(b, con->smb_info->user_agent); 1366 } 1367 buffer_append_string_len(b, CONST_STR_LEN("</D:getuseragent>")); 1368 found = 1; 1369 } 1370 else if (0 == strcmp(prop_name, "getroutersync")) { 1371 //- 20121206 Jerry add 1372 buffer_append_string_len(b,CONST_STR_LEN("<D:getroutersync>")); 1373 1374 share_link_info_t* c; 1375 int is_router_sync_folder = 0; 1376 buffer* temp = buffer_init(); 1377 1378 for (c = share_link_info_list; c; c = c->next) { 1379 1380 if(c->toshare != 2) 1381 continue; 1382 1383 buffer_append_string_buffer(temp, c->realpath); 1384 buffer_append_string(temp, "/"); 1385 buffer_append_string_buffer(temp, c->filename); 1386 1387 if(buffer_is_equal(temp,dst->rel_path)){ 1388 is_router_sync_folder = 1; 1389 break; 1390 } 1391 } 1392 1393 buffer_free(temp); 1394 1395 if(is_router_sync_folder==1) 1396 buffer_append_string(b, "1"); 1397 else 1398 buffer_append_string(b, "0"); 1399 1400 buffer_append_string_len(b, CONST_STR_LEN("</D:getroutersync>")); 1401 found = 1; 1402 } 1403 else if (0 == strcmp(prop_name, "getmetadata")) { 1404#if 1 1405 buffer_append_string_len(b,CONST_STR_LEN("<D:getmetadata>")); 1406 1407 if(is_dms_enabled()==1){ 1408 1409 int rows, i; 1410 sqlite3 *sql_minidlna = NULL; 1411 char **result; 1412 char sql_query[2048] = "\0"; 1413 1414 get_minidlna_db_path(p); 1415 1416 if (!buffer_is_empty(p->minidlna_db_file)) { 1417 if (SQLITE_OK != sqlite3_open(p->minidlna_db_file->ptr, &(sql_minidlna))) { 1418 Cdbg(DBE, "Fail to open minidlna db %s", p->minidlna_db_file->ptr); 1419 } 1420 } 1421 1422 if (sql_minidlna) { 1423 1424 int column_count = 11; 1425 sprintf(sql_query, "SELECT ID, TITLE, SIZE, TIMESTAMP, THUMBNAIL, RESOLUTION, CREATOR, ARTIST, MIME, ALBUM, ALBUM_ART from DETAILS"); 1426 1427 #if EMBEDDED_EANBLE 1428 if (0 == strcmp(dst->path->ptr, "/tmp")) 1429 sprintf(sql_query, "%s WHERE PATH = '%s'", sql_query, dst->path->ptr); 1430 else 1431 sprintf(sql_query, "%s WHERE PATH = '/tmp%s'", sql_query, dst->path->ptr); 1432 #else 1433 sprintf(sql_query, "%s WHERE PATH = '%s'", sql_query, dst->path->ptr); 1434 #endif 1435 1436 //Cdbg(DBE, "sql_query=%s", sql_query); 1437 1438 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 1439 if( rows ){ 1440 sqlite_int64 plID = strtoll(result[column_count], NULL, 10); 1441 char* plname = result[column_count+1]; 1442 char* thumbnail = result[column_count+4]; 1443 char* resolution = result[column_count+5]; 1444 char* creator = result[column_count+6]; 1445 char* artist = result[column_count+7]; 1446 char* mime = result[column_count+8]; 1447 char* album = result[column_count+9]; 1448 char* album_art = result[column_count+10]; 1449 1450 if(plname){ 1451 int thumb = atoi(thumbnail); 1452 1453 buffer_append_string_len(b, CONST_STR_LEN("<D:title>")); 1454 buffer_append_string(b, plname); 1455 buffer_append_string_len(b, CONST_STR_LEN("</D:title>")); 1456 1457 buffer_append_string_len(b, CONST_STR_LEN("<D:resolution>")); 1458 buffer_append_string(b, resolution); 1459 buffer_append_string_len(b, CONST_STR_LEN("</D:resolution>")); 1460 1461 buffer_append_string_len(b, CONST_STR_LEN("<D:creator><![CDATA[")); 1462 buffer_append_string(b, creator); 1463 buffer_append_string_len(b, CONST_STR_LEN("]]></D:creator>")); 1464 1465 buffer_append_string_len(b, CONST_STR_LEN("<D:artist><![CDATA[")); 1466 buffer_append_string(b, artist); 1467 buffer_append_string_len(b, CONST_STR_LEN("]]></D:artist>")); 1468 1469 buffer_append_string_len(b, CONST_STR_LEN("<D:mime>")); 1470 buffer_append_string(b, mime); 1471 buffer_append_string_len(b, CONST_STR_LEN("</D:mime>")); 1472 1473 buffer_append_string_len(b, CONST_STR_LEN("<D:thumb>")); 1474 //buffer_append_string(b, thumbnail); 1475 buffer_append_string_len(b, CONST_STR_LEN("1")); 1476 buffer_append_string_len(b, CONST_STR_LEN("</D:thumb>")); 1477 1478 //Cdbg(DBE, "plname=%s, thumb=%d, resolution=%s, creator=%s, artist=%s, mime=%s, album_art=%s", plname, thumb, resolution, creator, artist, mime, album_art); 1479 1480 #if 0 1481 char* image = NULL; 1482 if(thumb==1){ 1483 if(get_thumb_image(dst->path->ptr, &image)==1){ 1484 buffer_append_string_len(b, CONST_STR_LEN("<D:thumb_image>")); 1485 buffer_append_string(b, image); 1486 buffer_append_string_len(b, CONST_STR_LEN("</D:thumb_image>")); 1487 free(image); 1488 } 1489 } 1490 else{ 1491 sqlite_int64 plAlbumArt = (album_art ? strtoll(album_art, NULL, 10) : 0); 1492 if(get_album_cover_image(sql_minidlna, plAlbumArt, &image)==1){ 1493 buffer_append_string_len(b, CONST_STR_LEN("<D:thumb_image>")); 1494 buffer_append_string(b, image); 1495 buffer_append_string_len(b, CONST_STR_LEN("</D:thumb_image>")); 1496 free(image); 1497 } 1498 } 1499 #endif 1500 } 1501 } 1502 1503 sqlite3_free_table(result); 1504 } 1505 1506 sqlite3_close(sql_minidlna); 1507 } 1508 } 1509 1510#if 0 1511 //- http request test 1512 struct sockaddr_in their_addr; /* connector's address information */ 1513 int serverSocket = socket(AF_INET, SOCK_STREAM, 0); 1514 if (serverSocket == -1) 1515 Cdbg(DBE, "serverSocket == -1" ); 1516 1517 bzero(&(their_addr), sizeof(their_addr)); /* zero the rest of the struct */ 1518 their_addr.sin_family = AF_INET; /* host byte order */ 1519 their_addr.sin_port = htons(8082); /* short, network byte order */ 1520 their_addr.sin_addr.s_addr = htonl(INADDR_ANY); 1521 1522 bzero(&(their_addr.sin_zero), sizeof(their_addr.sin_zero)); /* zero the rest of the struct */ 1523 if (connect(serverSocket, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) { 1524 1525 Cdbg(DBE, "connect error"); 1526 } 1527 1528 //- http://imdbapi.org/?title=Batman Begins&type=xml 1529 char request[1024]="\0"; 1530 sprintf(request, "GET %s HTTP/1.0\r\nHOST:%s \r\n", "/?title=Batman&type=xml", "http://imdbapi.org/"); 1531 1532 Cdbg(DBE, "request = %s", request ); 1533 1534 if( send(serverSocket, &request, sizeof(request), 0) < 0 ) 1535 Cdbg(DBE, "send()"); 1536 1537 int numbytes; 1538 char buf[1024]; 1539 if ((numbytes=recv(serverSocket, buf, 1024, 0)) == -1) { 1540 Cdbg(DBE, "recv error"); 1541 } 1542 1543 buf[numbytes] = '\0'; 1544 1545 close(serverSocket); 1546 Cdbg(DBE, "buf=%s", buf); 1547 //////////////////////////////////// 1548#endif 1549 1550#if 0 1551 1552 char url[1024]="\0"; 1553 sprintf(url, "%s", "http://imdbapi.org/?title=Batman&type=xml"); 1554 1555 char init_upload_xml[1024]="/tmp/aaa.xml"; 1556 int status = sendRequest(init_upload_xml,url,NULL,NULL,NULL); 1557#endif 1558 1559 buffer_append_string_len(b, CONST_STR_LEN("</D:getmetadata>")); 1560 1561 found = 1; 1562#endif 1563 } 1564 /*else if (0 == strcmp(prop_name, "getname")) { 1565 //- 20120920 Jerry add 1566 buffer_append_string_len(b,CONST_STR_LEN("<D:getname>")); 1567 buffer_append_string_len(b,CONST_STR_LEN("sda")); 1568 buffer_append_string_len(b, CONST_STR_LEN("</D:getname>")); 1569 found = 1; 1570 }else if (0 == strcmp(prop_name, "getpath")) { 1571 //- 20120920 Jerry add 1572 buffer_append_string_len(b,CONST_STR_LEN("<D:getpath>")); 1573 buffer_append_string_buffer(b,dst->rel_path); 1574 buffer_append_string_len(b, CONST_STR_LEN("</D:getpath>")); 1575 found = 1; 1576 }*/ 1577 } 1578 1579 return found ? 0 : -1; 1580} 1581 1582static int webdav_get_property(server *srv, connection *con, plugin_data *p, physical *dst, char *prop_name, char *prop_ns, buffer *b) { 1583 if (0 == strcmp(prop_ns, "DAV:")) { 1584 /* a local 'live' property */ 1585 return webdav_get_live_property(srv, con, p, dst, prop_name, b); 1586 } else { 1587 int found = 0; 1588#ifdef USE_PROPPATCH 1589 sqlite3_stmt *stmt = p->conf.stmt_select_prop; 1590 1591 if (stmt) { 1592 /* perhaps it is in sqlite3 */ 1593 sqlite3_reset(stmt); 1594 1595 /* bind the values to the insert */ 1596 1597 sqlite3_bind_text(stmt, 1, 1598 CONST_BUF_LEN(dst->rel_path), 1599 SQLITE_TRANSIENT); 1600 sqlite3_bind_text(stmt, 2, 1601 prop_name, 1602 strlen(prop_name), 1603 SQLITE_TRANSIENT); 1604 sqlite3_bind_text(stmt, 3, 1605 prop_ns, 1606 strlen(prop_ns), 1607 SQLITE_TRANSIENT); 1608 1609 /* it is the PK */ 1610 while (SQLITE_ROW == sqlite3_step(stmt)) { 1611 /* there is a row for us, we only expect a single col 'value' */ 1612 webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b); 1613 found = 1; 1614 } 1615 } 1616#endif 1617 return found ? 0 : -1; 1618 } 1619 1620 /* not found */ 1621 return -1; 1622} 1623 1624typedef struct { 1625 char *ns; 1626 char *prop; 1627} webdav_property; 1628 1629static webdav_property live_properties[] = { 1630 { "DAV:", "creationdate" }, 1631 { "DAV:", "displayname" }, 1632 { "DAV:", "getcontentlanguage" }, 1633 { "DAV:", "getcontentlength" }, 1634 { "DAV:", "getcontenttype" }, 1635 { "DAV:", "getetag" }, 1636 { "DAV:", "getlastmodified" }, 1637 { "DAV:", "resourcetype" }, 1638 { "DAV:", "lockdiscovery" }, 1639 { "DAV:", "source" }, 1640 { "DAV:", "supportedlock" }, 1641 { "DAV:", "getmac" }, 1642 { "DAV:", "getonline" }, 1643 { "DAV:", "getuniqueid" }, 1644 { "DAV:", "gettype" }, 1645 { "DAV:", "getattr" }, 1646 { "DAV:", "getname" }, 1647 { "DAV:", "getpath" }, 1648 { "DAV:", "getuseragent" }, 1649 { "DAV:", "getroutersync" }, 1650 { "DAV:", "getmetadata" }, 1651 1652 { NULL, NULL } 1653}; 1654 1655typedef struct { 1656 webdav_property **ptr; 1657 1658 size_t used; 1659 size_t size; 1660} webdav_properties; 1661 1662static int webdav_get_props(server *srv, connection *con, plugin_data *p, physical *dst, webdav_properties *props, buffer *b_200, buffer *b_404) { 1663 size_t i; 1664 1665 if (props) { 1666 for (i = 0; i < props->used; i++) { 1667 webdav_property *prop; 1668 1669 prop = props->ptr[i]; 1670 1671 if (0 != webdav_get_property(srv, con, p, 1672 dst, prop->prop, prop->ns, b_200)) { 1673 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404); 1674 } 1675 } 1676 } else { 1677 for (i = 0; live_properties[i].prop; i++) { 1678 /* a local 'live' property */ 1679 webdav_get_live_property(srv, con, p, dst, live_properties[i].prop, b_200); 1680 } 1681 } 1682 1683 return 0; 1684} 1685 1686#ifdef USE_PROPPATCH 1687static int webdav_parse_chunkqueue(server *srv, connection *con, plugin_data *p, chunkqueue *cq, xmlDoc **ret_xml) { 1688 xmlParserCtxtPtr ctxt; 1689 xmlDoc *xml; 1690 int res; 1691 int err; 1692 1693 chunk *c; 1694 1695 UNUSED(con); 1696 1697 /* read the chunks in to the XML document */ 1698 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL); 1699 1700 for (c = cq->first; cq->bytes_out != cq->bytes_in; c = cq->first) { 1701 size_t weWant = cq->bytes_out - cq->bytes_in; 1702 size_t weHave; 1703 1704 switch(c->type) { 1705 case FILE_CHUNK: 1706 weHave = c->file.length - c->offset; 1707 1708 if (weHave > weWant) weHave = weWant; 1709 1710 /* xml chunks are always memory, mmap() is our friend */ 1711 if (c->file.mmap.start == MAP_FAILED) { 1712 if (-1 == c->file.fd && /* open the file if not already open */ 1713 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { 1714 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); 1715 1716 return -1; 1717 } 1718 1719 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) { 1720 log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 1721 strerror(errno), c->file.name, c->file.fd); 1722 close(c->file.fd); 1723 c->file.fd = -1; 1724 1725 return -1; 1726 } 1727 1728 close(c->file.fd); 1729 c->file.fd = -1; 1730 1731 c->file.mmap.length = c->file.length; 1732 1733 /* chunk_reset() or chunk_free() will cleanup for us */ 1734 } 1735 1736 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) { 1737 log_error_write(srv, __FILE__, __LINE__, "sodd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); 1738 } 1739 1740 chunkqueue_mark_written(cq, weHave); 1741 1742 break; 1743 case MEM_CHUNK: 1744 /* append to the buffer */ 1745 weHave = buffer_string_length(c->mem) - c->offset; 1746 1747 if (weHave > weWant) weHave = weWant; 1748 1749 if (p->conf.log_xml) { 1750 log_error_write(srv, __FILE__, __LINE__, "ss", "XML-request-body:", c->mem->ptr + c->offset); 1751 } 1752 1753 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) { 1754 log_error_write(srv, __FILE__, __LINE__, "sodd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); 1755 } 1756 1757 chunkqueue_mark_written(cq, weHave); 1758 1759 break; 1760 } 1761 } 1762 1763 switch ((err = xmlParseChunk(ctxt, 0, 0, 1))) { 1764 case XML_ERR_DOCUMENT_END: 1765 case XML_ERR_OK: 1766 break; 1767 default: 1768 log_error_write(srv, __FILE__, __LINE__, "sd", "xmlParseChunk failed at final packet:", err); 1769 break; 1770 } 1771 1772 xml = ctxt->myDoc; 1773 res = ctxt->wellFormed; 1774 xmlFreeParserCtxt(ctxt); 1775 1776 if (res == 0) { 1777 xmlFreeDoc(xml); 1778 } else { 1779 *ret_xml = xml; 1780 } 1781 1782 return res; 1783} 1784#endif 1785 1786#ifdef USE_LOCKS 1787static int webdav_lockdiscovery(server *srv, connection *con, 1788 buffer *locktoken, const char *lockscope, const char *locktype, int depth) { 1789 1790 buffer *b = buffer_init(); 1791 1792 response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken)); 1793 1794 response_header_overwrite(srv, con, 1795 CONST_STR_LEN("Content-Type"), 1796 CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 1797 1798 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")); 1799 1800 buffer_append_string_len(b,CONST_STR_LEN("<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n")); 1801 buffer_append_string_len(b,CONST_STR_LEN("<D:lockdiscovery>\n")); 1802 buffer_append_string_len(b,CONST_STR_LEN("<D:activelock>\n")); 1803 1804 buffer_append_string_len(b,CONST_STR_LEN("<D:lockscope>")); 1805 buffer_append_string_len(b,CONST_STR_LEN("<D:")); 1806 buffer_append_string(b, lockscope); 1807 buffer_append_string_len(b, CONST_STR_LEN("/>")); 1808 buffer_append_string_len(b,CONST_STR_LEN("</D:lockscope>\n")); 1809 1810 buffer_append_string_len(b,CONST_STR_LEN("<D:locktype>")); 1811 buffer_append_string_len(b,CONST_STR_LEN("<D:")); 1812 buffer_append_string(b, locktype); 1813 buffer_append_string_len(b, CONST_STR_LEN("/>")); 1814 buffer_append_string_len(b,CONST_STR_LEN("</D:locktype>\n")); 1815 1816 buffer_append_string_len(b,CONST_STR_LEN("<D:depth>")); 1817 buffer_append_string(b, depth == 0 ? "0" : "infinity"); 1818 buffer_append_string_len(b,CONST_STR_LEN("</D:depth>\n")); 1819 1820 buffer_append_string_len(b,CONST_STR_LEN("<D:timeout>")); 1821 buffer_append_string_len(b, CONST_STR_LEN("Second-600")); 1822 buffer_append_string_len(b,CONST_STR_LEN("</D:timeout>\n")); 1823 1824 buffer_append_string_len(b,CONST_STR_LEN("<D:owner>")); 1825 buffer_append_string_len(b,CONST_STR_LEN("</D:owner>\n")); 1826 1827 buffer_append_string_len(b,CONST_STR_LEN("<D:locktoken>")); 1828 buffer_append_string_len(b, CONST_STR_LEN("<D:href>")); 1829 buffer_append_string_buffer(b, locktoken); 1830 buffer_append_string_len(b, CONST_STR_LEN("</D:href>")); 1831 buffer_append_string_len(b,CONST_STR_LEN("</D:locktoken>\n")); 1832 1833 buffer_append_string_len(b,CONST_STR_LEN("</D:activelock>\n")); 1834 buffer_append_string_len(b,CONST_STR_LEN("</D:lockdiscovery>\n")); 1835 buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n")); 1836 1837 chunkqueue_append_buffer(con->write_queue, b); 1838 buffer_free(b); 1839 1840 return 0; 1841} 1842#endif 1843 1844/** 1845 * check if resource is having the right locks to access to resource 1846 * 1847 * 1848 * 1849 */ 1850static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) { 1851 int has_lock = 1; 1852 1853#ifdef USE_LOCKS 1854 data_string *ds; 1855 UNUSED(srv); 1856 1857 /** 1858 * This implementation is more fake than real 1859 * we need a parser for the If: header to really handle the full scope 1860 * 1861 * X-Litmus: locks: 11 (owner_modify) 1862 * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>) 1863 * - a tagged check: 1864 * if http://127.0.0.1:1025/dav/litmus/lockme is locked with 1865 * opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1, go on 1866 * 1867 * X-Litmus: locks: 16 (fail_cond_put) 1868 * If: (<DAV:no-lock> ["-1622396671"]) 1869 * - untagged: 1870 * go on if the resource has the etag [...] and the lock 1871 */ 1872 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) { 1873 /* Ooh, ooh. A if tag, now the fun begins. 1874 * 1875 * this can only work with a real parser 1876 **/ 1877 } else { 1878 /* we didn't provided a lock-token -> */ 1879 /* if the resource is locked -> 423 */ 1880 1881 sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri; 1882 1883 sqlite3_reset(stmt); 1884 1885 sqlite3_bind_text(stmt, 1, 1886 CONST_BUF_LEN(uri), 1887 SQLITE_TRANSIENT); 1888 1889 while (SQLITE_ROW == sqlite3_step(stmt)) { 1890 has_lock = 0; 1891 } 1892 } 1893#else 1894 UNUSED(srv); 1895 UNUSED(con); 1896 UNUSED(p); 1897 UNUSED(uri); 1898#endif 1899 1900 return has_lock; 1901} 1902 1903//- 20111209 Sungmin add 1904static const char* change_webdav_file_path(server *srv, connection *con, const char* source) 1905{ 1906 UNUSED(con); 1907 1908 config_values_t cv[] = { 1909 { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ 1910 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } 1911 }; 1912 1913 size_t i, j; 1914 for (i = 1; i < srv->config_context->used; i++) { 1915 array* alias = array_init(); 1916 cv[0].destination = alias; 1917 1918 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)) { 1919 continue; 1920 } 1921 1922 for (j = 0; j < alias->used; j++) { 1923 1924 data_string *ds = (data_string *)alias->data[j]; 1925 if( strncmp(source, ds->key->ptr, ds->key->used-1) == 0 ){ 1926 char buff[4096]; 1927 replace_str(source, ds->key->ptr, ds->value->ptr, buff ); 1928 array_free(alias); 1929 return buff; 1930 } 1931 } 1932 1933 array_free(alias); 1934 } 1935 1936 return source; 1937} 1938 1939URIHANDLER_FUNC(mod_webdav_subrequest_handler) { 1940 plugin_data *p = p_d; 1941 buffer *b; 1942 DIR *dir; 1943 data_string *ds; 1944 int depth = -1; 1945 struct stat st; 1946 buffer *prop_200; 1947 buffer *prop_404; 1948 webdav_properties *req_props; 1949 stat_cache_entry *sce = NULL; 1950 1951 UNUSED(srv); 1952 1953 if (!p->conf.enabled) return HANDLER_GO_ON; 1954 /* physical path is setup */ 1955 if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON; 1956 1957 /* PROPFIND need them */ 1958 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Depth"))) { 1959 depth = strtol(ds->value->ptr, NULL, 10); 1960 } 1961 1962#if EMBEDDED_EANBLE 1963 if( !con->srv_socket->is_ssl ){ 1964 if(srv->is_streaming_port_opend && con->request.http_method==HTTP_METHOD_GET){ 1965 } 1966 else{ 1967 con->http_status = 403; 1968 return HANDLER_FINISHED; 1969 } 1970 } 1971#endif 1972 1973 1974 Cdbg(DBE, "http_method=[%d][%s], depth=[%d], con->url->path=[%s]", 1975 con->request.http_method, get_http_method_name(con->request.http_method), 1976 depth, con->url.path->ptr); 1977 1978 switch (con->request.http_method) { 1979 case HTTP_METHOD_PROPFIND: 1980 1981 /* they want to know the properties of the directory */ 1982 req_props = NULL; 1983 1984 /* is there a content-body ? */ 1985 1986 switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) { 1987 case HANDLER_ERROR: 1988 if (errno == ENOENT) { 1989 con->http_status = 404; 1990 return HANDLER_FINISHED; 1991 } 1992 break; 1993 default: 1994 break; 1995 } 1996 1997 1998#ifdef USE_PROPPATCH 1999 /* any special requests or just allprop ? */ 2000 if (con->request.content_length) { 2001 xmlDocPtr xml; 2002 2003 if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { 2004 xmlNode *rootnode = xmlDocGetRootElement(xml); 2005 2006 force_assert(rootnode); 2007 2008 if (0 == xmlStrcmp(rootnode->name, BAD_CAST "propfind")) { 2009 xmlNode *cmd; 2010 2011 req_props = calloc(1, sizeof(*req_props)); 2012 2013 for (cmd = rootnode->children; cmd; cmd = cmd->next) { 2014 2015 if (0 == xmlStrcmp(cmd->name, BAD_CAST "prop")) { 2016 /* get prop by name */ 2017 xmlNode *prop; 2018 2019 for (prop = cmd->children; prop; prop = prop->next) { 2020 if (prop->type == XML_TEXT_NODE) continue; /* ignore WS */ 2021 2022 if (prop->ns && 2023 (0 == xmlStrcmp(prop->ns->href, BAD_CAST "")) && 2024 (0 != xmlStrcmp(prop->ns->prefix, BAD_CAST ""))) { 2025 size_t i; 2026 log_error_write(srv, __FILE__, __LINE__, "ss", 2027 "no name space for:", 2028 prop->name); 2029 2030 xmlFreeDoc(xml); 2031 2032 for (i = 0; i < req_props->used; i++) { 2033 free(req_props->ptr[i]->ns); 2034 free(req_props->ptr[i]->prop); 2035 free(req_props->ptr[i]); 2036 } 2037 free(req_props->ptr); 2038 free(req_props); 2039 2040 con->http_status = 400; 2041 return HANDLER_FINISHED; 2042 } 2043 2044 /* add property to requested list */ 2045 if (req_props->size == 0) { 2046 req_props->size = 16; 2047 req_props->ptr = malloc(sizeof(*(req_props->ptr)) * req_props->size); 2048 } else if (req_props->used == req_props->size) { 2049 req_props->size += 16; 2050 req_props->ptr = realloc(req_props->ptr, sizeof(*(req_props->ptr)) * req_props->size); 2051 } 2052 2053 req_props->ptr[req_props->used] = malloc(sizeof(webdav_property)); 2054 req_props->ptr[req_props->used]->ns = (char *)xmlStrdup(prop->ns ? prop->ns->href : (xmlChar *)""); 2055 req_props->ptr[req_props->used]->prop = (char *)xmlStrdup(prop->name); 2056 req_props->used++; 2057 } 2058 } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "propname")) { 2059 sqlite3_stmt *stmt = p->conf.stmt_select_propnames; 2060 2061 if (stmt) { 2062 /* get all property names (EMPTY) */ 2063 sqlite3_reset(stmt); 2064 /* bind the values to the insert */ 2065 2066 sqlite3_bind_text(stmt, 1, 2067 CONST_BUF_LEN(con->uri.path), 2068 SQLITE_TRANSIENT); 2069 2070 if (SQLITE_DONE != sqlite3_step(stmt)) { 2071 } 2072 } 2073 } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "allprop")) { 2074 /* get all properties (EMPTY) */ 2075 req_props = NULL; 2076 } 2077 } 2078 } 2079 2080 xmlFreeDoc(xml); 2081 } else { 2082 con->http_status = 400; 2083 return HANDLER_FINISHED; 2084 } 2085 } 2086#endif 2087 con->http_status = 207; 2088 2089 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 2090 2091 b = buffer_init(); 2092 2093 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")); 2094 2095 //buffer_append_string_len(b,CONST_STR_LEN("<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n")); 2096 buffer_append_string_len(b,CONST_STR_LEN("<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\" ")); 2097 2098 char usbdisk_path[50] = "/usbdisk"; 2099 2100#if EMBEDDED_EANBLE 2101 buffer_append_string_len(b, CONST_STR_LEN(" readonly=\"")); 2102 #ifndef APP_IPKG 2103 strcpy(usbdisk_path, "/"); 2104 strcat(usbdisk_path, nvram_get_productid()); 2105 #else 2106 char *productid = nvram_get_productid(); 2107 strcpy(usbdisk_path, "/"); 2108 strcat(usbdisk_path, productid); 2109 free(productid); 2110 #endif 2111 char* usbdisk_rel_path=NULL; 2112 char* usbdisk_share_folder=NULL; 2113 int qry_type=0; 2114 Cdbg(1, "con->physical.path->ptr=%s", con->physical.path->ptr); 2115 smbc_parse_mnt_path(con->physical.path->ptr, 2116 p->mnt_path->ptr, 2117 p->mnt_path->used-1, 2118 &usbdisk_rel_path, 2119 &usbdisk_share_folder); 2120 2121 if(usbdisk_share_folder!=NULL){ 2122 2123 int perm = smbc_get_usbdisk_permission(con->aidisk_username->ptr, usbdisk_rel_path, usbdisk_share_folder); 2124 2125 if(perm==3) 2126 buffer_append_string(b, "0"); 2127 else 2128 buffer_append_string(b, "1"); 2129 2130 qry_type = 0; 2131 } 2132 else{ 2133 buffer_append_string(b, "1"); 2134 qry_type = 1; 2135 } 2136 2137 //- Query Type 2138 buffer_append_string_len(b, CONST_STR_LEN("\" qtype=\"")); 2139 if(qry_type==1) 2140 buffer_append_string(b, "1"); 2141 else 2142 buffer_append_string(b, "0"); 2143 2144 //- Computer Name 2145 #ifndef APP_IPKG 2146 buffer_append_string_len(b, CONST_STR_LEN("\" computername=\"")); 2147 buffer_append_string(b, nvram_get_computer_name()); 2148 #else 2149 char *computer_name = nvram_get_computer_name(); 2150 buffer_append_string_len(b, CONST_STR_LEN("\" computername=\"")); 2151 buffer_append_string(b, computer_name); 2152 //buffer_append_string(b, nvram_get_computer_name()); 2153 free(computer_name); 2154 #endif 2155#else 2156 buffer_append_string_len(b, CONST_STR_LEN(" readonly=\"0")); 2157 2158 //- Query Type 2159 buffer_append_string_len(b, CONST_STR_LEN("\" qtype=\"")); 2160 if(strcmp(con->uri.path->ptr, usbdisk_path)==0) 2161 buffer_append_string(b, "1"); 2162 else 2163 buffer_append_string(b, "0"); 2164 2165 //- Computer Name 2166 buffer_append_string_len(b, CONST_STR_LEN("\" computername=\"WebDAV")); 2167#endif 2168 2169 buffer_append_string_len(b, CONST_STR_LEN("\" isusb=\"1")); 2170 2171 buffer_append_string_len(b,CONST_STR_LEN("\">\n")); 2172 2173 /* allprop */ 2174 2175 prop_200 = buffer_init(); 2176 prop_404 = buffer_init(); 2177 2178 switch(depth) { 2179 case 0: 2180 /* Depth: 0 */ 2181 webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404); 2182 2183 buffer_append_string_len(b,CONST_STR_LEN("<D:response>\n")); 2184 buffer_append_string_len(b,CONST_STR_LEN("<D:href>")); 2185 buffer_append_string_buffer(b, con->uri.scheme); 2186 buffer_append_string_len(b,CONST_STR_LEN("://")); 2187 buffer_append_string_buffer(b, con->uri.authority); 2188 buffer_append_string_encoded(b, CONST_BUF_LEN(con->uri.path), ENCODING_REL_URI); 2189 buffer_append_string_len(b,CONST_STR_LEN("</D:href>\n")); 2190 2191 if (!buffer_string_is_empty(prop_200)) { 2192 buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n")); 2193 buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n")); 2194 2195 buffer_append_string_buffer(b, prop_200); 2196 2197 buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n")); 2198 2199 buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 200 OK</D:status>\n")); 2200 2201 buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n")); 2202 } 2203 if (!buffer_string_is_empty(prop_404)) { 2204 buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n")); 2205 buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n")); 2206 2207 buffer_append_string_buffer(b, prop_404); 2208 2209 buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n")); 2210 2211 buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 404 Not Found</D:status>\n")); 2212 2213 buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n")); 2214 } 2215 2216 buffer_append_string_len(b,CONST_STR_LEN("</D:response>\n")); 2217 2218 break; 2219 case 1: 2220 if (NULL != (dir = opendir(con->physical.path->ptr))) { 2221 struct dirent *de; 2222 physical d; 2223 physical *dst = &(con->physical); 2224 2225 d.path = buffer_init(); 2226 d.rel_path = buffer_init(); 2227 2228 while(NULL != (de = readdir(dir))) { 2229 if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { 2230 continue; 2231 /* ignore the parent dir */ 2232 } 2233 2234 if ( de->d_name[0] == '.' ) { 2235 continue; 2236 //- ignore the hidden file 2237 } 2238 2239 if ( check_skip_folder_name(de->d_name) == 1 ) { 2240 continue; 2241 } 2242 2243 buffer_copy_buffer(d.path, dst->path); 2244 buffer_append_slash(d.path); 2245 2246 buffer_copy_buffer(d.rel_path, dst->rel_path); 2247 buffer_append_slash(d.rel_path); 2248 2249 if (de->d_name[0] == '.' && de->d_name[1] == '\0') { 2250 /* don't append the . */ 2251 } else { 2252 buffer_append_string(d.path, de->d_name); 2253 buffer_append_string(d.rel_path, de->d_name); 2254 } 2255 2256#if EMBEDDED_EANBLE 2257 int permission = -1; 2258 char* usbdisk_rel_sub_path = NULL; 2259 char* usbdisk_sub_share_folder = NULL; 2260 smbc_parse_mnt_path(d.path->ptr, 2261 p->mnt_path->ptr, 2262 p->mnt_path->used-1, 2263 &usbdisk_rel_sub_path, 2264 &usbdisk_sub_share_folder); 2265 2266 if( usbdisk_sub_share_folder != NULL ){ 2267 permission = smbc_get_usbdisk_permission(con->aidisk_username->ptr, usbdisk_rel_sub_path, usbdisk_sub_share_folder); 2268 2269 free(usbdisk_rel_sub_path); 2270 free(usbdisk_sub_share_folder); 2271 2272 if(permission!=1 && permission!=3) 2273 continue; 2274 } 2275 else 2276 free(usbdisk_rel_sub_path); 2277#endif 2278 2279 buffer_reset(prop_200); 2280 buffer_reset(prop_404); 2281 2282 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404); 2283 2284 buffer_append_string_len(b,CONST_STR_LEN("<D:response>\n")); 2285 buffer_append_string_len(b,CONST_STR_LEN("<D:href>")); 2286 buffer_append_string_buffer(b, con->uri.scheme); 2287 buffer_append_string_len(b,CONST_STR_LEN("://")); 2288 buffer_append_string_buffer(b, con->uri.authority); 2289 2290 if(con->share_link_shortpath->used){ 2291 char buff[4096]; 2292 char* tmp = replace_str(&d.rel_path->ptr[0], 2293 (char*)con->share_link_realpath->ptr, 2294 (char*)con->share_link_shortpath->ptr, 2295 (char *)&buff[0]); 2296 2297 buffer_append_string(b, "/"); 2298 buffer_append_string_encoded(b, tmp, strlen(tmp), ENCODING_REL_URI); 2299 } 2300 else{ 2301 //Cdbg(DBE, "d.rel_path=%s", d.rel_path->ptr); 2302 buffer_append_string_encoded(b, CONST_BUF_LEN(d.rel_path), ENCODING_REL_URI); 2303 } 2304 2305 buffer_append_string_len(b,CONST_STR_LEN("</D:href>\n")); 2306 2307 if (!buffer_string_is_empty(prop_200)) { 2308 buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n")); 2309 buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n")); 2310 2311 buffer_append_string_buffer(b, prop_200); 2312 2313 buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n")); 2314 2315 buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 200 OK</D:status>\n")); 2316 2317 buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n")); 2318 } 2319 if (!buffer_string_is_empty(prop_404)) { 2320 buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n")); 2321 buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n")); 2322 2323 buffer_append_string_buffer(b, prop_404); 2324 2325 buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n")); 2326 2327 buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 404 Not Found</D:status>\n")); 2328 2329 buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n")); 2330 } 2331 2332 buffer_append_string_len(b,CONST_STR_LEN("</D:response>\n")); 2333 } 2334 closedir(dir); 2335 buffer_free(d.path); 2336 buffer_free(d.rel_path); 2337 } 2338 break; 2339 } 2340 2341 if (req_props) { 2342 size_t i; 2343 for (i = 0; i < req_props->used; i++) { 2344 free(req_props->ptr[i]->ns); 2345 free(req_props->ptr[i]->prop); 2346 free(req_props->ptr[i]); 2347 } 2348 free(req_props->ptr); 2349 free(req_props); 2350 } 2351 2352 buffer_free(prop_200); 2353 buffer_free(prop_404); 2354 2355 buffer_append_string_len(b,CONST_STR_LEN("</D:multistatus>\n")); 2356 2357 if (p->conf.log_xml) { 2358 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b); 2359 } 2360 2361 chunkqueue_append_buffer(con->write_queue, b); 2362 buffer_free(b); 2363 2364 con->file_finished = 1; 2365 2366 return HANDLER_FINISHED; 2367 case HTTP_METHOD_MKCOL: 2368 if (p->conf.is_readonly) { 2369 con->http_status = 403; 2370 return HANDLER_FINISHED; 2371 } 2372 2373 if (con->request.content_length != 0) { 2374 /* we don't support MKCOL with a body */ 2375 con->http_status = 415; 2376 2377 return HANDLER_FINISHED; 2378 } 2379 2380 /* let's create the directory */ 2381 2382 if (-1 == mkdir(con->physical.path->ptr, WEBDAV_DIR_MODE)) { 2383 switch(errno) { 2384 case EPERM: 2385 con->http_status = 403; 2386 break; 2387 case ENOENT: 2388 case ENOTDIR: 2389 con->http_status = 409; 2390 break; 2391 case EEXIST: 2392 default: 2393 con->http_status = 405; /* not allowed */ 2394 break; 2395 } 2396 } else { 2397 log_sys_write(srv, "sbss", "Create folder", con->url.rel_path, "from ip", con->dst_addr_buf->ptr); 2398 con->http_status = 201; 2399 con->file_finished = 1; 2400 } 2401 2402 return HANDLER_FINISHED; 2403 case HTTP_METHOD_DELETE: 2404 if (p->conf.is_readonly) { 2405 con->http_status = 403; 2406 return HANDLER_FINISHED; 2407 } 2408 2409 /* does the client have a lock for this connection ? */ 2410 if (!webdav_has_lock(srv, con, p, con->uri.path)) { 2411 con->http_status = 423; 2412 return HANDLER_FINISHED; 2413 } 2414 2415 /* stat and unlink afterwards */ 2416 if (-1 == stat(con->physical.path->ptr, &st)) { 2417 /* don't about it yet, unlink will fail too */ 2418 switch(errno) { 2419 case ENOENT: 2420 con->http_status = 404; 2421 break; 2422 default: 2423 con->http_status = 403; 2424 break; 2425 } 2426 } else if (S_ISDIR(st.st_mode)) { 2427 buffer *multi_status_resp = buffer_init(); 2428 2429 if (webdav_delete_dir(srv, con, p, &(con->physical), multi_status_resp)) { 2430 /* we got an error somewhere in between, build a 207 */ 2431 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 2432 2433 b = buffer_init(); 2434 2435 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")); 2436 2437 buffer_append_string_len(b,CONST_STR_LEN("<D:multistatus xmlns:D=\"DAV:\">\n")); 2438 2439 buffer_append_string_buffer(b, multi_status_resp); 2440 2441 buffer_append_string_len(b,CONST_STR_LEN("</D:multistatus>\n")); 2442 2443 if (p->conf.log_xml) { 2444 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b); 2445 } 2446 2447 chunkqueue_append_buffer(con->write_queue, b); 2448 buffer_free(b); 2449 2450 con->http_status = 207; 2451 con->file_finished = 1; 2452 } else { 2453 /* everything went fine, remove the directory */ 2454 2455 if (-1 == rmdir(con->physical.path->ptr)) { 2456 switch(errno) { 2457 case ENOENT: 2458 con->http_status = 404; 2459 break; 2460 default: 2461 con->http_status = 501; 2462 break; 2463 } 2464 } else { 2465 log_sys_write(srv, "sbss", "Delete folder", con->url.rel_path, "from ip", con->dst_addr_buf->ptr); 2466 con->http_status = 204; 2467 } 2468 } 2469 2470 buffer_free(multi_status_resp); 2471 } else if (-1 == unlink(con->physical.path->ptr)) { 2472 switch(errno) { 2473 case EPERM: 2474 con->http_status = 403; 2475 break; 2476 case ENOENT: 2477 con->http_status = 404; 2478 break; 2479 default: 2480 con->http_status = 501; 2481 break; 2482 } 2483 } else { 2484 log_sys_write(srv, "sbss", "Delete file", con->url.rel_path, "from ip", con->dst_addr_buf->ptr); 2485 con->http_status = 204; 2486 } 2487 return HANDLER_FINISHED; 2488 case HTTP_METHOD_PUT: { 2489 int fd; 2490 chunkqueue *cq = con->request_content_queue; 2491 chunk *c; 2492 data_string *ds_range; 2493 2494 if (p->conf.is_readonly) { 2495 con->http_status = 403; 2496 return HANDLER_FINISHED; 2497 } 2498 2499 /* is a exclusive lock set on the source */ 2500 if (!webdav_has_lock(srv, con, p, con->uri.path)) { 2501 con->http_status = 423; 2502 return HANDLER_FINISHED; 2503 } 2504 2505 //- Sungmin add 2506 int autoCreateFolder = 0; 2507 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Auto-CreateFolder"))) { 2508 if (ds->value->used != 2 || 2509 (ds->value->ptr[0] != 'F' && 2510 ds->value->ptr[0] != 'T') ) { 2511 con->http_status = 400; 2512 return HANDLER_FINISHED; 2513 } 2514 autoCreateFolder = (ds->value->ptr[0] == 'F' ? 0 : 1); 2515 } 2516 2517 if(autoCreateFolder){ 2518 char* file_path = NULL; 2519 extract_filepath(con->physical.path->ptr, &file_path); 2520 createDirectory(file_path); 2521 free(file_path); 2522 } 2523 //////////////////////////////// 2524 2525 assert(chunkqueue_length(cq) == (off_t)con->request.content_length); 2526 2527 /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support 2528 * - most important Content-Range 2529 * 2530 * 2531 * Example: Content-Range: bytes 100-1037/1038 */ 2532 2533 if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) { 2534 const char *num = ds_range->value->ptr; 2535 off_t offset; 2536 char *err = NULL; 2537 2538 if (0 != strncmp(num, "bytes ", 6)) { 2539 con->http_status = 501; /* not implemented */ 2540 2541 return HANDLER_FINISHED; 2542 } 2543 2544 /* we only support <num>- ... */ 2545 2546 num += 6; 2547 2548 /* skip WS */ 2549 while (*num == ' ' || *num == '\t') num++; 2550 2551 if (*num == '\0') { 2552 con->http_status = 501; /* not implemented */ 2553 2554 return HANDLER_FINISHED; 2555 } 2556 2557 offset = strtoll(num, &err, 10); 2558 2559 if (*err != '-' || offset < 0) { 2560 con->http_status = 501; /* not implemented */ 2561 2562 return HANDLER_FINISHED; 2563 } 2564 2565 //- Sungmin modify if offset is zero, we create a new file. 2566 if(offset==0){ 2567 if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, WEBDAV_FILE_MODE))) { 2568 if (errno == ENOENT && 2569 -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, WEBDAV_FILE_MODE))) { 2570 /* we can't open the file */ 2571 switch(errno) { 2572 case EEXIST: 2573 con->http_status = 412; 2574 break; 2575 case EISDIR: 2576 con->http_status = 427; 2577 break; 2578 case ENOENT: 2579 /* at least one part in the middle wasn't existing */ 2580 con->http_status = 427; 2581 break; 2582 default: 2583 con->http_status = 403; 2584 break; 2585 } 2586 2587 return HANDLER_FINISHED; 2588 } 2589 else { 2590 con->http_status = 201; /* created */ 2591 } 2592 } 2593 else { 2594 con->http_status = 200; /* modified */ 2595 } 2596 } 2597 else{ 2598 if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, WEBDAV_FILE_MODE))) { 2599 switch (errno) { 2600 case ENOENT: 2601 con->http_status = 404; /* not found */ 2602 break; 2603 default: 2604 con->http_status = 403; /* not found */ 2605 break; 2606 } 2607 return HANDLER_FINISHED; 2608 } 2609 } 2610 2611 if (-1 == lseek(fd, offset, SEEK_SET)) { 2612 con->http_status = 501; /* not implemented */ 2613 2614 close(fd); 2615 2616 return HANDLER_FINISHED; 2617 } 2618 con->http_status = 200; /* modified */ 2619 } 2620 else { 2621 /* take what we have in the request-body and write it to a file */ 2622 2623 /* if the file doesn't exist, create it */ 2624 if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, WEBDAV_FILE_MODE))) { 2625 if (errno != ENOENT || 2626 -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, WEBDAV_FILE_MODE))) { 2627 /* we can't open the file */ 2628 con->http_status = 403; 2629 2630 return HANDLER_FINISHED; 2631 } 2632 else { 2633 con->http_status = 201; /* created */ 2634 } 2635 } 2636 else { 2637 con->http_status = 200; /* modified */ 2638 } 2639 } 2640 2641 con->file_finished = 1; 2642 2643 for (c = cq->first; c; c = cq->first) { 2644 int r = 0; 2645 2646 /* copy all chunks */ 2647 switch(c->type) { 2648 case FILE_CHUNK: 2649 2650 if (c->file.mmap.start == MAP_FAILED) { 2651 if (-1 == c->file.fd && /* open the file if not already open */ 2652 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { 2653 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); 2654 close(fd); 2655 return HANDLER_ERROR; 2656 } 2657 2658 if (MAP_FAILED == (c->file.mmap.start = mmap(NULL, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) { 2659 log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", 2660 strerror(errno), c->file.name, c->file.fd); 2661 close(c->file.fd); 2662 c->file.fd = -1; 2663 close(fd); 2664 return HANDLER_ERROR; 2665 } 2666 2667 c->file.mmap.length = c->file.length; 2668 2669 close(c->file.fd); 2670 c->file.fd = -1; 2671 2672 /* chunk_reset() or chunk_free() will cleanup for us */ 2673 } 2674 2675 if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) { 2676 switch(errno) { 2677 case ENOSPC: 2678 con->http_status = 507; 2679 2680 break; 2681 default: 2682 con->http_status = 403; 2683 break; 2684 } 2685 } 2686 break; 2687 case MEM_CHUNK: 2688 if ((r = write(fd, c->mem->ptr + c->offset, buffer_string_length(c->mem) - c->offset)) < 0) { 2689 switch(errno) { 2690 case ENOSPC: 2691 con->http_status = 507; 2692 2693 break; 2694 default: 2695 con->http_status = 403; 2696 break; 2697 } 2698 } 2699 break; 2700 } 2701 2702 if (r > 0) { 2703 chunkqueue_mark_written(cq, r); 2704 } else { 2705 break; 2706 } 2707 } 2708 close(fd); 2709 2710 return HANDLER_FINISHED; 2711 } 2712 case HTTP_METHOD_MOVE: 2713 case HTTP_METHOD_COPY: { 2714 buffer *destination = NULL; 2715 char *sep, *sep2, *start; 2716 int overwrite = 1; 2717 2718 if (p->conf.is_readonly) { 2719 con->http_status = 403; 2720 return HANDLER_FINISHED; 2721 } 2722 2723 /* is a exclusive lock set on the source */ 2724 if (con->request.http_method == HTTP_METHOD_MOVE) { 2725 if (!webdav_has_lock(srv, con, p, con->uri.path)) { 2726 con->http_status = 423; 2727 return HANDLER_FINISHED; 2728 } 2729 } 2730 2731 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) { 2732 destination = ds->value; 2733 } else { 2734 con->http_status = 400; 2735 return HANDLER_FINISHED; 2736 } 2737 2738 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Overwrite"))) { 2739 if (buffer_string_length(ds->value) != 1 || 2740 (ds->value->ptr[0] != 'F' && 2741 ds->value->ptr[0] != 'T') ) { 2742 con->http_status = 400; 2743 return HANDLER_FINISHED; 2744 } 2745 overwrite = (ds->value->ptr[0] == 'F' ? 0 : 1); 2746 } 2747 /* let's parse the Destination 2748 * 2749 * http://127.0.0.1:1025/dav/litmus/copydest 2750 * 2751 * - host has to be the same as the Host: header we got 2752 * - we have to stay inside the document root 2753 * - the query string is thrown away 2754 * */ 2755 2756 buffer_reset(p->uri.scheme); 2757 buffer_reset(p->uri.path_raw); 2758 buffer_reset(p->uri.authority); 2759 2760 start = destination->ptr; 2761 2762 if (NULL == (sep = strstr(start, "://"))) { 2763 con->http_status = 400; 2764 return HANDLER_FINISHED; 2765 } 2766 buffer_copy_string_len(p->uri.scheme, start, sep - start); 2767 2768 start = sep + 3; 2769 2770 if (NULL == (sep = strchr(start, '/'))) { 2771 con->http_status = 400; 2772 return HANDLER_FINISHED; 2773 } 2774 if (NULL != (sep2 = memchr(start, '@', sep - start))) { 2775 /* skip login information */ 2776 start = sep2 + 1; 2777 } 2778 buffer_copy_string_len(p->uri.authority, start, sep - start); 2779 2780 start = sep + 1; 2781 2782 if (NULL == (sep = strchr(start, '?'))) { 2783 /* no query string, good */ 2784 buffer_copy_string(p->uri.path_raw, start); 2785 } else { 2786 buffer_copy_string_len(p->uri.path_raw, start, sep - start); 2787 } 2788 2789 if (!buffer_is_equal(p->uri.authority, con->uri.authority)) { 2790 /* not the same host */ 2791 con->http_status = 502; 2792 return HANDLER_FINISHED; 2793 } 2794 2795 buffer_copy_buffer(p->tmp_buf, p->uri.path_raw); 2796 buffer_urldecode_path(p->tmp_buf); 2797 buffer_path_simplify(p->uri.path, p->tmp_buf); 2798 2799 //- 20121115 Sungmin add for router sync. 2800 if(con->share_link_shortpath->used){ 2801 2802 char* a; 2803 if (NULL != ( a = strstr(p->uri.path->ptr, con->share_link_shortpath->ptr))){ 2804 char buff[4096]; 2805 replace_str( a, 2806 con->share_link_shortpath->ptr, 2807 con->share_link_realpath->ptr, 2808 buff ); 2809 buffer_copy_string( p->uri.path, buff ); 2810 } 2811 else{ 2812 con->http_status = 502; 2813 return HANDLER_FINISHED; 2814 } 2815 } 2816 2817 //- 20111209 Sungmin add 2818 buffer_copy_string(p->uri.path, change_webdav_file_path(srv, con, p->uri.path->ptr)); 2819 2820 /* we now have a URI which is clean. transform it into a physical path */ 2821 buffer_copy_buffer(p->physical.doc_root, con->physical.doc_root); 2822 buffer_copy_buffer(p->physical.rel_path, p->uri.path); 2823 2824 if (con->conf.force_lowercase_filenames) { 2825 buffer_to_lower(p->physical.rel_path); 2826 } 2827 2828 buffer_copy_buffer(p->physical.path, p->physical.doc_root); 2829 buffer_append_slash(p->physical.path); 2830 buffer_copy_buffer(p->physical.basedir, p->physical.path); 2831 2832 /* don't add a second / */ 2833 if (p->physical.rel_path->ptr[0] == '/') { 2834 buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, buffer_string_length(p->physical.rel_path) - 1); 2835 } else { 2836 buffer_append_string_buffer(p->physical.path, p->physical.rel_path); 2837 } 2838 2839 /* let's see if the source is a directory 2840 * if yes, we fail with 501 */ 2841 2842 if (-1 == stat(con->physical.path->ptr, &st)) { 2843 /* don't about it yet, unlink will fail too */ 2844 switch(errno) { 2845 case ENOENT: 2846 con->http_status = 404; 2847 break; 2848 default: 2849 con->http_status = 403; 2850 break; 2851 } 2852 } else if (S_ISDIR(st.st_mode)) { 2853 int r; 2854 /* src is a directory */ 2855 2856 if (-1 == stat(p->physical.path->ptr, &st)) { 2857 //- dst is not exist. 2858 if(in_the_same_folder(con->physical.path, p->physical.path)) { 2859 if( rename(con->physical.path->ptr, p->physical.path->ptr) ) { 2860 con->http_status = 403; 2861 } else { 2862 con->http_status = 201; //Created 2863 log_sys_write(srv, "sbsbss", "Move", con->physical.rel_path, "to", p->physical.rel_path ,"from ip", con->dst_addr_buf->ptr); 2864 } 2865 2866 con->file_finished = 1; 2867 return HANDLER_FINISHED; 2868 } else if (-1 == mkdir(p->physical.path->ptr, WEBDAV_DIR_MODE)) { 2869 con->http_status = 403; 2870 return HANDLER_FINISHED; 2871 } 2872 } 2873 else if (!S_ISDIR(st.st_mode)) { 2874 //- dst is not folder. 2875 if (overwrite == 0) { 2876 /* copying into a non-dir ? */ 2877 con->http_status = 409; 2878 return HANDLER_FINISHED; 2879 } else { 2880 unlink(p->physical.path->ptr); 2881 if (-1 == mkdir(p->physical.path->ptr, WEBDAV_DIR_MODE)) { 2882 con->http_status = 403; 2883 return HANDLER_FINISHED; 2884 } 2885 } 2886 } 2887 else if (S_ISDIR(st.st_mode)) { 2888 //- dst folder is exist. 2889 if (overwrite == 0) { 2890 /* copying into a non-dir ? */ 2891 con->http_status = 412; 2892 return HANDLER_FINISHED; 2893 } 2894 } 2895 2896 /* copy the content of src to dest */ 2897 if (0 != (r = webdav_copy_dir(srv, con, p, &(con->physical), &(p->physical), overwrite))) { 2898 con->http_status = r; 2899 return HANDLER_FINISHED; 2900 } 2901 if (con->request.http_method == HTTP_METHOD_MOVE) { 2902 b = buffer_init(); 2903 webdav_delete_dir(srv, con, p, &(con->physical), b); /* content */ 2904 buffer_free(b); 2905 Cdbg(DBE, "Move %s to %s from ip", con->url.rel_path->ptr, p->physical.rel_path->ptr); 2906 rmdir(con->physical.path->ptr); 2907 2908 log_sys_write(srv, "sbsbss", "Move", con->url.rel_path, "to", p->physical.rel_path ,"from ip", con->dst_addr_buf->ptr); 2909 } 2910 con->http_status = 201; 2911 con->file_finished = 1; 2912 } else { 2913 /* it is just a file, good */ 2914 int r; 2915 2916 /* does the client have a lock for this connection ? */ 2917 if (!webdav_has_lock(srv, con, p, p->uri.path)) { 2918 con->http_status = 423; 2919 return HANDLER_FINISHED; 2920 } 2921 2922 /* destination exists */ 2923 if (0 == (r = stat(p->physical.path->ptr, &st))) { 2924 if (S_ISDIR(st.st_mode)) { 2925 if (overwrite == 0) { 2926 /* copying into a non-dir ? */ 2927 con->http_status = 409; 2928 return HANDLER_FINISHED; 2929 } 2930 2931 /* file to dir/ 2932 * append basename to physical path */ 2933 2934 if (NULL != (sep = strrchr(con->physical.path->ptr, '/'))) { 2935 buffer_append_string(p->physical.path, sep); 2936 r = stat(p->physical.path->ptr, &st); 2937 } 2938 } 2939 } 2940 2941 if (-1 == r) { 2942 con->http_status = 201; /* we will create a new one */ 2943 con->file_finished = 1; 2944 2945 switch(errno) { 2946 case ENOTDIR: 2947 con->http_status = 409; 2948 return HANDLER_FINISHED; 2949 } 2950 } else if (overwrite == 0) { 2951 /* destination exists, but overwrite is not set */ 2952 con->http_status = 412; 2953 return HANDLER_FINISHED; 2954 } else { 2955 con->http_status = 204; /* resource already existed */ 2956 } 2957 2958 if (con->request.http_method == HTTP_METHOD_MOVE) { 2959 /* try a rename */ 2960 2961 if (0 == rename(con->physical.path->ptr, p->physical.path->ptr)) { 2962#ifdef USE_PROPPATCH 2963 sqlite3_stmt *stmt; 2964 2965 stmt = p->conf.stmt_delete_uri; 2966 if (stmt) { 2967 2968 sqlite3_reset(stmt); 2969 2970 /* bind the values to the insert */ 2971 sqlite3_bind_text(stmt, 1, 2972 CONST_BUF_LEN(con->uri.path), 2973 SQLITE_TRANSIENT); 2974 2975 if (SQLITE_DONE != sqlite3_step(stmt)) { 2976 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move(delete old) failed:", sqlite3_errmsg(p->conf.sql)); 2977 } 2978 } 2979 2980 stmt = p->conf.stmt_move_uri; 2981 if (stmt) { 2982 2983 sqlite3_reset(stmt); 2984 2985 /* bind the values to the insert */ 2986 sqlite3_bind_text(stmt, 1, 2987 CONST_BUF_LEN(p->uri.path), 2988 SQLITE_TRANSIENT); 2989 2990 sqlite3_bind_text(stmt, 2, 2991 CONST_BUF_LEN(con->uri.path), 2992 SQLITE_TRANSIENT); 2993 2994 if (SQLITE_DONE != sqlite3_step(stmt)) { 2995 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql)); 2996 } 2997 } 2998#endif 2999 log_sys_write(srv, "sbsbss", "Move", con->url.rel_path, "to", p->physical.rel_path ,"from ip", con->dst_addr_buf->ptr); 3000 3001 return HANDLER_FINISHED; 3002 } 3003 3004 /* rename failed, fall back to COPY + DELETE */ 3005 } 3006 3007 if (0 != (r = webdav_copy_file(srv, con, p, &(con->physical), &(p->physical), overwrite))) { 3008 con->http_status = r; 3009 3010 return HANDLER_FINISHED; 3011 } 3012 3013 if (con->request.http_method == HTTP_METHOD_MOVE) { 3014 b = buffer_init(); 3015 webdav_delete_file(srv, con, p, &(con->physical), b); 3016 buffer_free(b); 3017 3018 log_sys_write(srv, "sbsbss", "Move", con->url.rel_path, "to", p->physical.rel_path ,"from ip", con->dst_addr_buf->ptr); 3019 } 3020 } 3021 3022 return HANDLER_FINISHED; 3023 } 3024 case HTTP_METHOD_PROPPATCH: 3025 if (p->conf.is_readonly) { 3026 con->http_status = 403; 3027 return HANDLER_FINISHED; 3028 } 3029 3030 if (!webdav_has_lock(srv, con, p, con->uri.path)) { 3031 con->http_status = 423; 3032 return HANDLER_FINISHED; 3033 } 3034 3035 /* check if destination exists */ 3036 if (-1 == stat(con->physical.path->ptr, &st)) { 3037 switch(errno) { 3038 case ENOENT: 3039 con->http_status = 404; 3040 break; 3041 } 3042 } 3043 3044#ifdef USE_PROPPATCH 3045 if (con->request.content_length) { 3046 xmlDocPtr xml; 3047 3048 if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { 3049 xmlNode *rootnode = xmlDocGetRootElement(xml); 3050 3051 if (0 == xmlStrcmp(rootnode->name, BAD_CAST "propertyupdate")) { 3052 xmlNode *cmd; 3053 char *err = NULL; 3054 int empty_ns = 0; /* send 400 on a empty namespace attribute */ 3055 3056 /* start response */ 3057 3058 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "BEGIN TRANSACTION", NULL, NULL, &err)) { 3059 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err); 3060 sqlite3_free(err); 3061 3062 goto propmatch_cleanup; 3063 } 3064 3065 /* a UPDATE request, we know 'set' and 'remove' */ 3066 for (cmd = rootnode->children; cmd; cmd = cmd->next) { 3067 xmlNode *props; 3068 /* either set or remove */ 3069 3070 if ((0 == xmlStrcmp(cmd->name, BAD_CAST "set")) || 3071 (0 == xmlStrcmp(cmd->name, BAD_CAST "remove"))) { 3072 3073 sqlite3_stmt *stmt; 3074 3075 stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ? 3076 p->conf.stmt_delete_prop : p->conf.stmt_update_prop; 3077 3078 for (props = cmd->children; props; props = props->next) { 3079 if (0 == xmlStrcmp(props->name, BAD_CAST "prop")) { 3080 xmlNode *prop; 3081 int r; 3082 3083 prop = props->children; 3084 3085 if (prop->ns && 3086 (0 == xmlStrcmp(prop->ns->href, BAD_CAST "")) && 3087 (0 != xmlStrcmp(prop->ns->prefix, BAD_CAST ""))) { 3088 log_error_write(srv, __FILE__, __LINE__, "ss", 3089 "no name space for:", 3090 prop->name); 3091 3092 empty_ns = 1; 3093 break; 3094 } 3095 3096 sqlite3_reset(stmt); 3097 3098 /* bind the values to the insert */ 3099 3100 sqlite3_bind_text(stmt, 1, 3101 CONST_BUF_LEN(con->uri.path), 3102 SQLITE_TRANSIENT); 3103 sqlite3_bind_text(stmt, 2, 3104 (char *)prop->name, 3105 strlen((char *)prop->name), 3106 SQLITE_TRANSIENT); 3107 if (prop->ns) { 3108 sqlite3_bind_text(stmt, 3, 3109 (char *)prop->ns->href, 3110 strlen((char *)prop->ns->href), 3111 SQLITE_TRANSIENT); 3112 } else { 3113 sqlite3_bind_text(stmt, 3, 3114 "", 3115 0, 3116 SQLITE_TRANSIENT); 3117 } 3118 if (stmt == p->conf.stmt_update_prop) { 3119 sqlite3_bind_text(stmt, 4, 3120 (char *)xmlNodeGetContent(prop), 3121 strlen((char *)xmlNodeGetContent(prop)), 3122 SQLITE_TRANSIENT); 3123 } 3124 3125 if (SQLITE_DONE != (r = sqlite3_step(stmt))) { 3126 log_error_write(srv, __FILE__, __LINE__, "ss", 3127 "sql-set failed:", sqlite3_errmsg(p->conf.sql)); 3128 } 3129 } 3130 } 3131 if (empty_ns) break; 3132 } 3133 } 3134 3135 if (empty_ns) { 3136 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "ROLLBACK", NULL, NULL, &err)) { 3137 log_error_write(srv, __FILE__, __LINE__, "ss", "can't rollback transaction:", err); 3138 sqlite3_free(err); 3139 3140 goto propmatch_cleanup; 3141 } 3142 3143 con->http_status = 400; 3144 } else { 3145 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) { 3146 log_error_write(srv, __FILE__, __LINE__, "ss", "can't commit transaction:", err); 3147 sqlite3_free(err); 3148 3149 goto propmatch_cleanup; 3150 } 3151 con->http_status = 200; 3152 } 3153 con->file_finished = 1; 3154 3155 return HANDLER_FINISHED; 3156 } 3157 3158propmatch_cleanup: 3159 3160 xmlFreeDoc(xml); 3161 } else { 3162 con->http_status = 400; 3163 return HANDLER_FINISHED; 3164 } 3165 } 3166#endif 3167 con->http_status = 501; 3168 return HANDLER_FINISHED; 3169 case HTTP_METHOD_LOCK: 3170 /** 3171 * a mac wants to write 3172 * 3173 * LOCK /dav/expire.txt HTTP/1.1\r\n 3174 * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n 3175 * Accept: * / *\r\n 3176 * Depth: 0\r\n 3177 * Timeout: Second-600\r\n 3178 * Content-Type: text/xml; charset=\"utf-8\"\r\n 3179 * Content-Length: 229\r\n 3180 * Connection: keep-alive\r\n 3181 * Host: 192.168.178.23:1025\r\n 3182 * \r\n 3183 * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n 3184 * <D:lockinfo xmlns:D=\"DAV:\">\n 3185 * <D:lockscope><D:exclusive/></D:lockscope>\n 3186 * <D:locktype><D:write/></D:locktype>\n 3187 * <D:owner>\n 3188 * <D:href>http://www.apple.com/webdav_fs/</D:href>\n 3189 * </D:owner>\n 3190 * </D:lockinfo>\n 3191 */ 3192 3193 if (depth != 0 && depth != -1) { 3194 con->http_status = 400; 3195 3196 return HANDLER_FINISHED; 3197 } 3198 3199#ifdef USE_LOCKS 3200 if (con->request.content_length) { 3201 xmlDocPtr xml; 3202 buffer *hdr_if = NULL; 3203 3204 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) { 3205 hdr_if = ds->value; 3206 } 3207 3208 /* we don't support Depth: Infinity on locks */ 3209 if (hdr_if == NULL && depth == -1) { 3210 con->http_status = 409; /* Conflict */ 3211 3212 return HANDLER_FINISHED; 3213 } 3214 3215 if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { 3216 xmlNode *rootnode = xmlDocGetRootElement(xml); 3217 3218 force_assert(rootnode); 3219 3220 if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) { 3221 xmlNode *lockinfo; 3222 const xmlChar *lockscope = NULL, *locktype = NULL; /* TODO: compiler says unused: *owner = NULL; */ 3223 3224 for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) { 3225 if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) { 3226 xmlNode *value; 3227 for (value = lockinfo->children; value; value = value->next) { 3228 if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) || 3229 (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) { 3230 lockscope = value->name; 3231 } else { 3232 con->http_status = 400; 3233 3234 xmlFreeDoc(xml); 3235 return HANDLER_FINISHED; 3236 } 3237 } 3238 } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) { 3239 xmlNode *value; 3240 for (value = lockinfo->children; value; value = value->next) { 3241 if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) { 3242 locktype = value->name; 3243 } else { 3244 con->http_status = 400; 3245 3246 xmlFreeDoc(xml); 3247 return HANDLER_FINISHED; 3248 } 3249 } 3250 3251 } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) { 3252 } 3253 } 3254 3255 if (lockscope && locktype) { 3256 sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri; 3257 3258 /* is this resourse already locked ? */ 3259 3260 /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout 3261 * FROM locks 3262 * WHERE resource = ? */ 3263 3264 if (stmt) { 3265 3266 sqlite3_reset(stmt); 3267 3268 sqlite3_bind_text(stmt, 1, 3269 CONST_BUF_LEN(p->uri.path), 3270 SQLITE_TRANSIENT); 3271 3272 /* it is the PK */ 3273 while (SQLITE_ROW == sqlite3_step(stmt)) { 3274 /* we found a lock 3275 * 1. is it compatible ? 3276 * 2. is it ours */ 3277 char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2); 3278 3279 if (strcmp(sql_lockscope, "exclusive")) { 3280 con->http_status = 423; 3281 } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) { 3282 /* resourse is locked with a shared lock 3283 * client wants exclusive */ 3284 con->http_status = 423; 3285 } 3286 } 3287 if (con->http_status == 423) { 3288 xmlFreeDoc(xml); 3289 return HANDLER_FINISHED; 3290 } 3291 } 3292 3293 stmt = p->conf.stmt_create_lock; 3294 if (stmt) { 3295 /* create a lock-token */ 3296 //uuid_t id; 3297 char uuid[37] /* 36 + \0 */; 3298 3299 sprintf( uuid, "%d", rand() ); 3300 3301 //uuid_generate(id); 3302 //uuid_unparse(id, uuid); 3303 3304 buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("opaquelocktoken:")); 3305 buffer_append_string(p->tmp_buf, uuid); 3306 3307 /* "CREATE TABLE locks (" 3308 * " locktoken TEXT NOT NULL," 3309 * " resource TEXT NOT NULL," 3310 * " lockscope TEXT NOT NULL," 3311 * " locktype TEXT NOT NULL," 3312 * " owner TEXT NOT NULL," 3313 * " depth INT NOT NULL," 3314 */ 3315 3316 sqlite3_reset(stmt); 3317 3318 /* locktoken */ 3319 sqlite3_bind_text(stmt, 1, 3320 CONST_BUF_LEN(p->tmp_buf), 3321 SQLITE_TRANSIENT); 3322 3323 /* resource */ 3324 sqlite3_bind_text(stmt, 2, 3325 CONST_BUF_LEN(con->uri.path), 3326 SQLITE_TRANSIENT); 3327 3328 /* lockscope */ 3329 sqlite3_bind_text(stmt, 3, 3330 (const char *)lockscope, 3331 xmlStrlen(lockscope), 3332 SQLITE_TRANSIENT); 3333 3334 /* locktype */ 3335 sqlite3_bind_text(stmt, 4, 3336 (const char *)locktype, 3337 xmlStrlen(locktype), 3338 SQLITE_TRANSIENT); 3339 3340 /* owner */ 3341 sqlite3_bind_text(stmt, 5, 3342 "", 3343 0, 3344 SQLITE_TRANSIENT); 3345 3346 /* depth */ 3347 sqlite3_bind_int(stmt, 6, 3348 depth); 3349 3350 3351 if (SQLITE_DONE != sqlite3_step(stmt)) { 3352 log_error_write(srv, __FILE__, __LINE__, "ss", 3353 "create lock:", sqlite3_errmsg(p->conf.sql)); 3354 } 3355 3356 /* looks like we survived */ 3357 webdav_lockdiscovery(srv, con, p->tmp_buf, (const char *)lockscope, (const char *)locktype, depth); 3358 3359 con->http_status = 201; 3360 con->file_finished = 1; 3361 } 3362 } 3363 } 3364 3365 xmlFreeDoc(xml); 3366 return HANDLER_FINISHED; 3367 } else { 3368 con->http_status = 400; 3369 return HANDLER_FINISHED; 3370 } 3371 } else { 3372 3373 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) { 3374 buffer *locktoken = ds->value; 3375 sqlite3_stmt *stmt = p->conf.stmt_refresh_lock; 3376 3377 /* remove the < > around the token */ 3378 if (buffer_string_length(locktoken) < 5) { 3379 con->http_status = 400; 3380 3381 return HANDLER_FINISHED; 3382 } 3383 3384 buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, buffer_string_length(locktoken) - 4); 3385 3386 sqlite3_reset(stmt); 3387 3388 sqlite3_bind_text(stmt, 1, 3389 CONST_BUF_LEN(p->tmp_buf), 3390 SQLITE_TRANSIENT); 3391 3392 if (SQLITE_DONE != sqlite3_step(stmt)) { 3393 log_error_write(srv, __FILE__, __LINE__, "ss", 3394 "refresh lock:", sqlite3_errmsg(p->conf.sql)); 3395 } 3396 3397 webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0); 3398 3399 con->http_status = 200; 3400 con->file_finished = 1; 3401 return HANDLER_FINISHED; 3402 } else { 3403 /* we need a lock-token to refresh */ 3404 con->http_status = 400; 3405 3406 return HANDLER_FINISHED; 3407 } 3408 } 3409 break; 3410#else 3411 con->http_status = 501; 3412 return HANDLER_FINISHED; 3413#endif 3414 case HTTP_METHOD_UNLOCK: 3415#ifdef USE_LOCKS 3416 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) { 3417 buffer *locktoken = ds->value; 3418 sqlite3_stmt *stmt = p->conf.stmt_remove_lock; 3419 3420 /* remove the < > around the token */ 3421 if (buffer_string_length(locktoken) < 3) { 3422 con->http_status = 400; 3423 3424 return HANDLER_FINISHED; 3425 } 3426 3427 /** 3428 * FIXME: 3429 * 3430 * if the resourse is locked: 3431 * - by us: unlock 3432 * - by someone else: 401 3433 * if the resource is not locked: 3434 * - 412 3435 * */ 3436 3437 buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, buffer_string_length(locktoken) - 2); 3438 3439 sqlite3_reset(stmt); 3440 3441 sqlite3_bind_text(stmt, 1, 3442 CONST_BUF_LEN(p->tmp_buf), 3443 SQLITE_TRANSIENT); 3444 3445 sqlite3_bind_text(stmt, 2, 3446 CONST_BUF_LEN(con->uri.path), 3447 SQLITE_TRANSIENT); 3448 3449 if (SQLITE_DONE != sqlite3_step(stmt)) { 3450 log_error_write(srv, __FILE__, __LINE__, "ss", 3451 "remove lock:", sqlite3_errmsg(p->conf.sql)); 3452 } 3453 3454 if (0 == sqlite3_changes(p->conf.sql)) { 3455 con->http_status = 401; 3456 } else { 3457 con->http_status = 204; 3458 } 3459 return HANDLER_FINISHED; 3460 } else { 3461 /* we need a lock-token to unlock */ 3462 con->http_status = 400; 3463 3464 return HANDLER_FINISHED; 3465 } 3466 break; 3467#else 3468 con->http_status = 501; 3469 return HANDLER_FINISHED; 3470#endif 3471 3472 case HTTP_METHOD_WOL:{ 3473 con->http_status = 200; 3474 return HANDLER_FINISHED; 3475 } 3476 3477 case HTTP_METHOD_GSL:{ 3478#if EMBEDDED_EANBLE 3479 if(!con->srv_socket->is_ssl){ 3480 con->http_status = 403; 3481 return HANDLER_FINISHED; 3482 } 3483#endif 3484 buffer *buffer_url = NULL; 3485 buffer *buffer_filename = NULL; 3486 buffer *buffer_result_share_link = NULL; 3487 int expire = 1; 3488 int toShare = 1; 3489 Cdbg(DBE, "do HTTP_METHOD_GSL...................."); 3490 3491 if (p->conf.is_readonly) { 3492 con->http_status = 403; 3493 return HANDLER_FINISHED; 3494 } 3495 3496 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "URL"))) { 3497 buffer_url = ds->value; 3498 } else { 3499 con->http_status = 400; 3500 return HANDLER_FINISHED; 3501 } 3502 3503 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "FILENAME"))) { 3504 buffer_filename = ds->value; 3505 } else { 3506 con->http_status = 400; 3507 return HANDLER_FINISHED; 3508 } 3509 3510 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "EXPIRE"))) { 3511 expire = atoi(ds->value->ptr); 3512 } else { 3513 con->http_status = 400; 3514 return HANDLER_FINISHED; 3515 } 3516 3517 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TOSHARE"))) { 3518 toShare = atoi(ds->value->ptr); 3519 } 3520 3521 int sharelink_save_count = get_sharelink_save_count(); 3522 int file_count = 0; 3523 3524 char* tmp_filename = strdup(buffer_filename->ptr); 3525 char *pch = strtok(tmp_filename, ";"); 3526 while(pch!=NULL){ 3527 file_count++; 3528 pch = strtok(NULL,";"); 3529 } 3530 free(tmp_filename); 3531 3532 if(toShare==1&&sharelink_save_count+file_count>srv->srvconf.max_sharelink){ 3533 con->http_status = 405; 3534 return HANDLER_FINISHED; 3535 } 3536 3537 char auth[100]="\0"; 3538 if(con->aidisk_username->used && con->aidisk_passwd->used) 3539 sprintf(auth, "%s:%s", con->aidisk_username->ptr, con->aidisk_passwd->ptr); 3540 else{ 3541 con->http_status = 400; 3542 return HANDLER_FINISHED; 3543 } 3544 3545 char* base64_auth = ldb_base64_encode(auth, strlen(auth)); 3546 3547 if( generate_sharelink(srv, 3548 con, 3549 buffer_filename->ptr, 3550 buffer_url->ptr, 3551 base64_auth, 3552 expire, 3553 toShare, 3554 &buffer_result_share_link) == 0){ 3555 free(base64_auth); 3556 con->http_status = 400; 3557 return HANDLER_FINISHED; 3558 } 3559 3560 con->http_status = 200; 3561 3562 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 3563 3564 b = buffer_init(); 3565 3566 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>")); 3567 buffer_append_string_len(b,CONST_STR_LEN("<result>")); 3568 buffer_append_string_len(b,CONST_STR_LEN("<sharelink>")); 3569 buffer_append_string_buffer(b,buffer_result_share_link); 3570 buffer_append_string_len(b,CONST_STR_LEN("</sharelink>")); 3571 buffer_append_string_len(b,CONST_STR_LEN("</result>")); 3572 3573 chunkqueue_append_buffer(con->write_queue, b); 3574 buffer_free(b); 3575 3576 con->file_finished = 1; 3577 3578 buffer_free(buffer_result_share_link); 3579 free(base64_auth); 3580 3581 if(toShare==1) 3582 save_sharelink_list(srv); 3583 3584 return HANDLER_FINISHED; 3585 } 3586 3587 case HTTP_METHOD_GETSRVTIME:{ 3588#if EMBEDDED_EANBLE 3589 if(!con->srv_socket->is_ssl){ 3590 con->http_status = 403; 3591 return HANDLER_FINISHED; 3592 } 3593#endif 3594 3595 char stime[1024]="\0"; 3596 time_t server_time = time(NULL); 3597 sprintf(stime, "%ld", server_time); 3598 Cdbg(DBE, "do HTTP_METHOD_GETSRVTIME....................%s", stime); 3599 3600 con->http_status = 200; 3601 3602 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 3603 3604 b = buffer_init(); 3605 3606 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")); 3607 buffer_append_string_len(b,CONST_STR_LEN("<result>\n")); 3608 buffer_append_string_len(b,CONST_STR_LEN("<servertime>\n")); 3609 buffer_append_string(b,stime); 3610 buffer_append_string_len(b,CONST_STR_LEN("</servertime>\n")); 3611 buffer_append_string_len(b,CONST_STR_LEN("</result>\n")); 3612 3613 chunkqueue_append_buffer(con->write_queue, b); 3614 buffer_free(b); 3615 3616 con->file_finished = 1; 3617 return HANDLER_FINISHED; 3618 } 3619 3620 case HTTP_METHOD_GETROUTERMAC:{ 3621 3622#if EMBEDDED_EANBLE 3623 char* router_mac = nvram_get_router_mac(); 3624#else 3625 char router_mac[20]="\0"; 3626 get_mac_address("eth0", &router_mac); 3627#endif 3628 3629 con->http_status = 200; 3630 3631 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 3632 3633 b = buffer_init(); 3634 3635 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")); 3636 buffer_append_string_len(b,CONST_STR_LEN("<result>\n")); 3637 buffer_append_string_len(b,CONST_STR_LEN("<mac>\n")); 3638 buffer_append_string(b,router_mac); 3639 buffer_append_string_len(b,CONST_STR_LEN("</mac>\n")); 3640 buffer_append_string_len(b,CONST_STR_LEN("</result>\n")); 3641 3642 chunkqueue_append_buffer(con->write_queue, b); 3643 buffer_free(b); 3644 3645 con->file_finished = 1; 3646#if EMBEDDED_EANBLE 3647#ifdef APP_IPKG 3648 free(router_mac); 3649#endif 3650#endif 3651 return HANDLER_FINISHED; 3652 } 3653 3654 case HTTP_METHOD_GETFIRMVER:{ 3655 3656#if EMBEDDED_EANBLE 3657 if(!con->srv_socket->is_ssl){ 3658 con->http_status = 403; 3659 return HANDLER_FINISHED; 3660 } 3661#endif 3662 3663#if EMBEDDED_EANBLE 3664 char* firmware_version = nvram_get_firmware_version(); 3665 char* build_no = nvram_get_build_no(); 3666#else 3667 char* firmware_version = "1.0.0"; 3668 char* build_no = "0"; 3669#endif 3670 3671 con->http_status = 200; 3672 3673 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 3674 3675 b = buffer_init(); 3676 3677 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")); 3678 buffer_append_string_len(b,CONST_STR_LEN("<result>\n")); 3679 buffer_append_string_len(b,CONST_STR_LEN("<version>\n")); 3680 buffer_append_string(b,firmware_version); 3681 buffer_append_string(b,"."); 3682 buffer_append_string(b,build_no); 3683 buffer_append_string_len(b,CONST_STR_LEN("</version>\n")); 3684 buffer_append_string_len(b,CONST_STR_LEN("</result>\n")); 3685 3686 chunkqueue_append_buffer(con->write_queue, b); 3687 buffer_free(b); 3688 3689 con->file_finished = 1; 3690#if EMBEDDED_EANBLE 3691#ifdef APP_IPKG 3692 free(firmware_version); 3693 free(build_no); 3694#endif 3695#endif 3696 return HANDLER_FINISHED; 3697 } 3698 3699#if 0 3700 case HTTP_METHOD_GETROUTERINFO:{ 3701#if EMBEDDED_EANBLE 3702 if(!con->srv_socket->is_ssl){ 3703 con->http_status = 403; 3704 return HANDLER_FINISHED; 3705 } 3706#endif 3707 3708 Cdbg(DBE, "do HTTP_METHOD_GETROUTERINFO...................."); 3709 3710 char stime[1024]="\0"; 3711 time_t server_time = time(NULL); 3712 sprintf(stime, "%ld", server_time); 3713 3714#if EMBEDDED_EANBLE 3715 char* router_mac = nvram_get_router_mac(); 3716 3717 char* firmware_version = nvram_get_firmware_version(); 3718 char* build_no = nvram_get_build_no(); 3719 3720 char* modal_name = nvram_get_productid(); 3721 3722 //- Computer Name 3723 char* computer_name = nvram_get_computer_name(); 3724 char* st_webdav_mode = nvram_get_st_webdav_mode(); 3725 char* webdav_http_port = nvram_get_webdav_http_port(); 3726 char* webdav_https_port = nvram_get_webdav_https_port(); 3727 char* http_enable = nvram_get_http_enable(); 3728 char* lan_http_port = "80"; 3729 char* lan_https_port = nvram_get_lan_https_port(); 3730 char* misc_http_x = nvram_get_misc_http_x(); 3731 char* misc_http_port = nvram_get_misc_http_port(); 3732 char* misc_https_port = nvram_get_misc_https_port(); 3733 char* ddns_host_name = nvram_get_ddns_host_name(); 3734 char* disk_path = "/mnt/"; 3735 char* wan_ip = nvram_get_wan_ip(); 3736 char *usbdiskname = nvram_get_productid(); 3737 3738 //- Get aicloud version 3739 #ifdef APP_IPKG 3740 char* aicloud_version_file = "/opt/lib/ipkg/info/aicloud.control"; 3741 char* aicloud_app_type = "install"; 3742 char* smartsync_version_file = "/opt/lib/ipkg/info/smartsync.control"; 3743 #else 3744 char* aicloud_version_file = "/usr/lighttpd/control"; 3745 char* aicloud_app_type = "embed"; 3746 char* smartsync_version_file = "/usr/lighttpd/smartsync_control"; 3747 #endif 3748 char aicloud_version[30]="\0"; 3749 char smartsync_version[30]="\0"; 3750 char *swpjverno = nvram_get_swpjverno(); 3751 char *extendno = nvram_get_extendno(); 3752 3753 char *https_crt_cn = nvram_get_https_crt_cn(); 3754 3755 char *apps_sq = nvram_get_apps_sq(); 3756#ifdef USE_TCAPI 3757 char *is_dsl_platform = "1"; 3758#else 3759 char *is_dsl_platform = "0"; 3760#endif 3761 3762#else 3763 char router_mac[20]="\0"; 3764 get_mac_address("eth0", &router_mac); 3765 3766 char* firmware_version = "1.0.0"; 3767 char* build_no = "0"; 3768 3769 char* modal_name = "WebDAV"; 3770 3771 //- Computer Name 3772 char* computer_name = "WebDAV"; 3773 char* st_webdav_mode = "0"; 3774 char* webdav_http_port = "8082"; 3775 char* webdav_https_port = "443"; 3776 char* http_enable = "2"; 3777 char* lan_http_port = "80"; 3778 char* lan_https_port = "8443"; 3779 char* misc_http_x = "0"; 3780 char* misc_http_port = "8080"; 3781 char* misc_https_port = "8443"; 3782 char* ddns_host_name = ""; 3783 char* disk_path = "/mnt/"; 3784 char* wan_ip = "192.168.1.10"; 3785 char *usbdiskname = "usbdisk"; 3786 3787 //- Get aicloud version 3788 char* aicloud_version_file = "/usr/css/control"; 3789 char* smartsync_version_file = "/usr/css/smartsync_control"; 3790 char aicloud_version[30]="\0"; 3791 char smartsync_version[30]="\0"; 3792 char *swpjverno = ""; 3793 char *extendno = ""; 3794 char* aicloud_app_type = "embed"; 3795 3796 char *https_crt_cn = "192.168.1.1"; 3797 3798 char *apps_sq = "0"; 3799 char *is_dsl_platform = "0"; 3800#endif 3801 int sharelink_save_count = get_sharelink_save_count(); 3802 int dms_enable = is_dms_enabled(); 3803 int jffs_supported = is_jffs_supported(); 3804 3805 if(buffer_is_empty(srv->srvconf.aicloud_version)){ 3806 //- Parser version file 3807 FILE* fp2; 3808 char line[128]; 3809 if((fp2 = fopen(aicloud_version_file, "r")) != NULL){ 3810 memset(line, 0, sizeof(line)); 3811 while(fgets(line, 128, fp2) != NULL){ 3812 if(strncmp(line, "Version:", 8)==0){ 3813 strncpy(aicloud_version, line + 9, strlen(line)-8); 3814 } 3815 } 3816 fclose(fp2); 3817 } 3818 } 3819 else{ 3820 strcpy(aicloud_version, srv->srvconf.aicloud_version->ptr); 3821 } 3822 3823 if(buffer_is_empty(srv->srvconf.smartsync_version)){ 3824 //- Parser version file 3825 FILE* fp2; 3826 char line[128]; 3827 if((fp2 = fopen(smartsync_version_file, "r")) != NULL){ 3828 memset(line, 0, sizeof(line)); 3829 while(fgets(line, 128, fp2) != NULL){ 3830 if(strncmp(line, "Version:", 8)==0){ 3831 strncpy(smartsync_version, line + 9, strlen(line)-8); 3832 } 3833 } 3834 fclose(fp2); 3835 } 3836 } 3837 else{ 3838 strcpy(smartsync_version, srv->srvconf.smartsync_version->ptr); 3839 } 3840 3841#ifndef APP_IPKG 3842 if( swpjverno!=NULL && strncmp(swpjverno,"", 1)!=0){ 3843 strcpy(aicloud_version, swpjverno); 3844 if(extendno!=NULL && strncmp(extendno,"", 1)!=0) 3845 { 3846 strcat(aicloud_version, "_"); 3847 strcat(aicloud_version, extendno); 3848 } 3849 } 3850#endif 3851 con->http_status = 200; 3852 3853 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 3854 3855 b = buffer_init(); 3856 3857 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>")); 3858 buffer_append_string_len(b,CONST_STR_LEN("<result>")); 3859 buffer_append_string_len(b,CONST_STR_LEN("<servertime>")); 3860 buffer_append_string(b,stime); 3861 buffer_append_string_len(b,CONST_STR_LEN("</servertime>")); 3862 buffer_append_string_len(b,CONST_STR_LEN("<mac>")); 3863 buffer_append_string(b,router_mac); 3864 buffer_append_string_len(b,CONST_STR_LEN("</mac>")); 3865 buffer_append_string_len(b,CONST_STR_LEN("<version>")); 3866 buffer_append_string(b,firmware_version); 3867 buffer_append_string(b,"."); 3868 buffer_append_string(b,build_no); 3869 buffer_append_string_len(b,CONST_STR_LEN("</version>")); 3870 buffer_append_string_len(b,CONST_STR_LEN("<aicloud_version>")); 3871 buffer_append_string(b,aicloud_version); 3872 buffer_append_string_len(b,CONST_STR_LEN("</aicloud_version>")); 3873 buffer_append_string_len(b,CONST_STR_LEN("<extendno>")); 3874 if(extendno!=NULL && strncmp(extendno,"", 1)!=0) buffer_append_string(b,extendno); 3875 buffer_append_string_len(b,CONST_STR_LEN("</extendno>")); 3876 buffer_append_string_len(b,CONST_STR_LEN("<aicloud_app_type>")); 3877 buffer_append_string(b,aicloud_app_type); 3878 buffer_append_string_len(b,CONST_STR_LEN("</aicloud_app_type>")); 3879 buffer_append_string_len(b,CONST_STR_LEN("<smartsync_version>")); 3880 buffer_append_string(b,smartsync_version); 3881 buffer_append_string_len(b,CONST_STR_LEN("</smartsync_version>")); 3882 buffer_append_string_len(b,CONST_STR_LEN("<modalname>")); 3883 buffer_append_string(b,modal_name); 3884 buffer_append_string_len(b,CONST_STR_LEN("</modalname>")); 3885 buffer_append_string_len(b,CONST_STR_LEN("<computername>")); 3886 buffer_append_string(b,computer_name); 3887 buffer_append_string_len(b,CONST_STR_LEN("</computername>")); 3888 buffer_append_string_len(b,CONST_STR_LEN("<usbdiskname>")); 3889 buffer_append_string(b,usbdiskname); 3890 buffer_append_string_len(b,CONST_STR_LEN("</usbdiskname>")); 3891 buffer_append_string_len(b,CONST_STR_LEN("<webdav_mode>")); 3892 buffer_append_string(b,st_webdav_mode); 3893 buffer_append_string_len(b,CONST_STR_LEN("</webdav_mode>")); 3894 buffer_append_string_len(b,CONST_STR_LEN("<http_port>")); 3895 buffer_append_string(b,webdav_http_port); 3896 buffer_append_string_len(b,CONST_STR_LEN("</http_port>")); 3897 buffer_append_string_len(b,CONST_STR_LEN("<https_port>")); 3898 buffer_append_string(b,webdav_https_port); 3899 buffer_append_string_len(b,CONST_STR_LEN("</https_port>")); 3900 buffer_append_string_len(b,CONST_STR_LEN("<http_enable>")); 3901 buffer_append_string(b,http_enable); 3902 buffer_append_string_len(b,CONST_STR_LEN("</http_enable>")); 3903 buffer_append_string_len(b,CONST_STR_LEN("<lan_http_port>")); 3904 buffer_append_string(b,lan_http_port); 3905 buffer_append_string_len(b,CONST_STR_LEN("</lan_http_port>")); 3906 buffer_append_string_len(b,CONST_STR_LEN("<lan_https_port>")); 3907 buffer_append_string(b,lan_https_port); 3908 buffer_append_string_len(b,CONST_STR_LEN("</lan_https_port>")); 3909 buffer_append_string_len(b,CONST_STR_LEN("<misc_http_enable>")); 3910 buffer_append_string(b,misc_http_x); 3911 buffer_append_string_len(b,CONST_STR_LEN("</misc_http_enable>")); 3912 buffer_append_string_len(b,CONST_STR_LEN("<misc_http_port>")); 3913 buffer_append_string(b,misc_http_port); 3914 buffer_append_string_len(b,CONST_STR_LEN("</misc_http_port>")); 3915 buffer_append_string_len(b,CONST_STR_LEN("<misc_https_port>")); 3916 buffer_append_string(b,misc_https_port); 3917 buffer_append_string_len(b,CONST_STR_LEN("</misc_https_port>")); 3918 buffer_append_string_len(b,CONST_STR_LEN("<last_login_info>")); 3919 if(buffer_is_empty(srv->last_login_info)) 3920 buffer_append_string(b,""); 3921 else 3922 buffer_append_string(b,srv->last_login_info->ptr); 3923 buffer_append_string_len(b,CONST_STR_LEN("</last_login_info>")); 3924 buffer_append_string_len(b,CONST_STR_LEN("<ddns_host_name>")); 3925 buffer_append_string(b,ddns_host_name); 3926 buffer_append_string_len(b,CONST_STR_LEN("</ddns_host_name>")); 3927 buffer_append_string_len(b,CONST_STR_LEN("<wan_ip>")); 3928 buffer_append_string(b,wan_ip); 3929 buffer_append_string_len(b,CONST_STR_LEN("</wan_ip>")); 3930 buffer_append_string_len(b,CONST_STR_LEN("<dms_enable>")); 3931 buffer_append_string(b, ((dms_enable==1) ? "1" : "0")); 3932 buffer_append_string_len(b,CONST_STR_LEN("</dms_enable>")); 3933 buffer_append_string_len(b,CONST_STR_LEN("<account_manager_enable>")); 3934 buffer_append_string(b, "0"); 3935 buffer_append_string_len(b,CONST_STR_LEN("</account_manager_enable>")); 3936 buffer_append_string_len(b,CONST_STR_LEN("<https_crt_cn>")); 3937 buffer_append_string(b,https_crt_cn); 3938 buffer_append_string_len(b,CONST_STR_LEN("</https_crt_cn>")); 3939 buffer_append_string_len(b,CONST_STR_LEN("<app_installation_url>")); 3940 buffer_append_string(b, buffer_is_empty(srv->srvconf.app_installation_url) ? "" : srv->srvconf.app_installation_url->ptr); 3941 buffer_append_string_len(b,CONST_STR_LEN("</app_installation_url>")); 3942 buffer_append_string_len(b,CONST_STR_LEN("<apps_sq>")); 3943 buffer_append_string(b,apps_sq); 3944 buffer_append_string_len(b,CONST_STR_LEN("</apps_sq>")); 3945 buffer_append_string_len(b,CONST_STR_LEN("<is_dsl_platform>")); 3946 buffer_append_string(b,is_dsl_platform); 3947 buffer_append_string_len(b,CONST_STR_LEN("</is_dsl_platform>")); 3948 buffer_append_string_len(b,CONST_STR_LEN("<used_sharelink>")); 3949 char used_sharelink[5] = "\0"; 3950 sprintf(used_sharelink, "%d", sharelink_save_count); 3951 buffer_append_string(b, used_sharelink); 3952 buffer_append_string_len(b,CONST_STR_LEN("</used_sharelink>")); 3953 buffer_append_string_len(b,CONST_STR_LEN("<max_sharelink>")); 3954 char max_sharelink[5] = "\0"; 3955 sprintf(max_sharelink, "%d", srv->srvconf.max_sharelink); 3956 buffer_append_string(b, max_sharelink); 3957 buffer_append_string_len(b,CONST_STR_LEN("</max_sharelink>")); 3958 3959 //DIR *dir; 3960 if (NULL != (dir = opendir(disk_path))) { 3961 3962 buffer_append_string_len(b,CONST_STR_LEN("<disk_space>")); 3963 3964 struct dirent *de; 3965 3966 while(NULL != (de = readdir(dir))) { 3967 3968 if ( de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0' ) { 3969 continue; 3970 //- ignore the parent dir 3971 } 3972 3973 if ( de->d_name[0] == '.' ) { 3974 continue; 3975 //- ignore the hidden file 3976 } 3977 3978 buffer_append_string_len(b,CONST_STR_LEN("<item>")); 3979 3980 char querycmd[100] = "\0"; 3981 3982 sprintf(querycmd, "df|grep -i '%s%s'", disk_path, de->d_name); 3983 3984 buffer_append_string_len(b,CONST_STR_LEN("<DiskName>")); 3985 buffer_append_string(b,de->d_name); 3986 buffer_append_string_len(b,CONST_STR_LEN("</DiskName>")); 3987 3988 char mybuffer[BUFSIZ]="\0"; 3989 FILE* fp = popen( querycmd, "r"); 3990 if(fp){ 3991 int len = fread(mybuffer, sizeof(char), BUFSIZ, fp); 3992 mybuffer[len-1]="\0"; 3993 pclose(fp); 3994 3995 char * pch; 3996 pch = strtok(mybuffer, " "); 3997 int count=1; 3998 while(pch!=NULL){ 3999 if(count==3){ 4000 buffer_append_string_len(b,CONST_STR_LEN("<DiskUsed>")); 4001 buffer_append_string(b,pch); 4002 buffer_append_string_len(b,CONST_STR_LEN("</DiskUsed>")); 4003 } 4004 else if(count==4){ 4005 buffer_append_string_len(b,CONST_STR_LEN("<DiskAvailable>")); 4006 buffer_append_string(b,pch); 4007 buffer_append_string_len(b,CONST_STR_LEN("</DiskAvailable>")); 4008 } 4009 else if(count==5){ 4010 buffer_append_string_len(b,CONST_STR_LEN("<DiskUsedPercent>")); 4011 buffer_append_string(b,pch); 4012 buffer_append_string_len(b,CONST_STR_LEN("</DiskUsedPercent>")); 4013 } 4014 4015 //- Next 4016 pch = strtok(NULL," "); 4017 count++; 4018 } 4019 4020 } 4021 4022 buffer_append_string_len(b,CONST_STR_LEN("</item>")); 4023 } 4024 4025 buffer_append_string_len(b,CONST_STR_LEN("</disk_space>")); 4026 4027 closedir(dir); 4028 } 4029 4030 buffer_append_string_len(b,CONST_STR_LEN("</result>")); 4031 4032 chunkqueue_append_buffer(con->write_queue, b); 4033 buffer_free(b); 4034 4035 con->file_finished = 1; 4036#if EMBEDDED_EANBLE 4037#ifdef APP_IPKG 4038 free(router_mac); 4039 free(firmware_version); 4040 free(build_no); 4041 free(modal_name); 4042 free(computer_name); 4043 free(st_webdav_mode); 4044 free(webdav_http_port); 4045 free(webdav_https_port); 4046 free(misc_http_x); 4047 free(misc_http_port); 4048 free(ddns_host_name); 4049 free(wan_ip); 4050 free(http_enable); 4051 free(misc_https_port); 4052 if(swpjverno!=NULL) 4053 free(swpjverno); 4054 if(extendno!=NULL) 4055 free(extendno); 4056 free(https_crt_cn); 4057#endif 4058#endif 4059 return HANDLER_FINISHED; 4060 } 4061#endif 4062 4063 case HTTP_METHOD_RESCANSMBPC:{ 4064#if EMBEDDED_EANBLE 4065 if(!con->srv_socket->is_ssl){ 4066 con->http_status = 403; 4067 return HANDLER_FINISHED; 4068 } 4069#endif 4070 Cdbg(DBE, "do HTTP_METHOD_RESCANSMBPC"); 4071 4072 stop_arpping_process(); 4073 4074 #if EMBEDDED_EANBLE 4075 nvram_set_smbdav_str(""); 4076 #else 4077 unlink("/tmp/arpping_list"); 4078 #endif 4079 4080 con->http_status = 200; 4081 con->file_finished = 1; 4082 return HANDLER_FINISHED; 4083 } 4084 4085 case HTTP_METHOD_PROPFINDMEDIALIST:{ 4086#if EMBEDDED_EANBLE 4087 if(!con->srv_socket->is_ssl){ 4088 con->http_status = 403; 4089 return HANDLER_FINISHED; 4090 } 4091#endif 4092 4093 int dms_enable = is_dms_enabled(); 4094 4095 if(dms_enable == 0){ 4096 //- Service Not Available 4097 con->http_status = 503; 4098 return HANDLER_FINISHED; 4099 } 4100 4101 /* they want to know the properties of the directory */ 4102 req_props = NULL; 4103 4104 /* is there a content-body ? */ 4105 switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) { 4106 case HANDLER_ERROR: 4107 if (errno == ENOENT) { 4108 con->http_status = 404; 4109 return HANDLER_FINISHED; 4110 } 4111 break; 4112 default: 4113 break; 4114 } 4115 4116#ifdef USE_PROPPATCH 4117 /* any special requests or just allprop ? */ 4118 if (con->request.content_length) { 4119 xmlDocPtr xml; 4120 4121 if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { 4122 xmlNode *rootnode = xmlDocGetRootElement(xml); 4123 4124 assert(rootnode); 4125 4126 if (0 == xmlStrcmp(rootnode->name, BAD_CAST "propfind")) { 4127 xmlNode *cmd; 4128 4129 req_props = calloc(1, sizeof(*req_props)); 4130 4131 for (cmd = rootnode->children; cmd; cmd = cmd->next) { 4132 4133 if (0 == xmlStrcmp(cmd->name, BAD_CAST "prop")) { 4134 /* get prop by name */ 4135 xmlNode *prop; 4136 for (prop = cmd->children; prop; prop = prop->next) { 4137 if (prop->type == XML_TEXT_NODE) continue; /* ignore WS */ 4138 if (prop->ns && 4139 (0 == xmlStrcmp(prop->ns->href, BAD_CAST "")) && 4140 (0 != xmlStrcmp(prop->ns->prefix, BAD_CAST ""))) { 4141 size_t i; 4142 log_error_write(srv, __FILE__, __LINE__, "ss", 4143 "no name space for:", 4144 prop->name); 4145 4146 xmlFreeDoc(xml); 4147 4148 for (i = 0; i < req_props->used; i++) { 4149 free(req_props->ptr[i]->ns); 4150 free(req_props->ptr[i]->prop); 4151 free(req_props->ptr[i]); 4152 } 4153 free(req_props->ptr); 4154 free(req_props); 4155 con->http_status = 400; 4156 return HANDLER_FINISHED; 4157 } 4158 4159 /* add property to requested list */ 4160 if (req_props->size == 0) { 4161 req_props->size = 16; 4162 req_props->ptr = malloc(sizeof(*(req_props->ptr)) * req_props->size); 4163 } else if (req_props->used == req_props->size) { 4164 req_props->size += 16; 4165 req_props->ptr = realloc(req_props->ptr, sizeof(*(req_props->ptr)) * req_props->size); 4166 } 4167 4168 req_props->ptr[req_props->used] = malloc(sizeof(webdav_property)); 4169 req_props->ptr[req_props->used]->ns = (char *)xmlStrdup(prop->ns ? prop->ns->href : (xmlChar *)""); 4170 req_props->ptr[req_props->used]->prop = (char *)xmlStrdup(prop->name); 4171 req_props->used++; 4172 } 4173 } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "propname")) { 4174 sqlite3_stmt *stmt = p->conf.stmt_select_propnames; 4175 4176 if (stmt) { 4177 /* get all property names (EMPTY) */ 4178 sqlite3_reset(stmt); 4179 /* bind the values to the insert */ 4180 4181 sqlite3_bind_text(stmt, 1, 4182 con->uri.path->ptr, 4183 con->uri.path->used - 1, 4184 SQLITE_TRANSIENT); 4185 4186 if (SQLITE_DONE != sqlite3_step(stmt)) { 4187 } 4188 } 4189 } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "allprop")) { 4190 /* get all properties (EMPTY) */ 4191 req_props = NULL; 4192 } 4193 } 4194 } 4195 4196 xmlFreeDoc(xml); 4197 } else { 4198 con->http_status = 400; 4199 return HANDLER_FINISHED; 4200 } 4201 } 4202#endif 4203 4204#ifdef USE_MINIDLNA_DB 4205 Cdbg(DBE, "do HTTP_METHOD_PROPFINDMEDIALIST"); 4206 4207 sqlite3 *sql_minidlna = NULL; 4208 buffer* media_type = NULL; //- 0: All(default), 1: Image, 2:Audio, 3:Video 4209 buffer* start = NULL; //- start query index 4210 buffer* end = NULL; //- end query index 4211 buffer* keyword = NULL; //- query keyword 4212 buffer* orderby = NULL; //- query sortby 4213 buffer* orderrule = NULL; //- sort rule: DESC, ASC 4214 buffer* parentid = NULL; //- parentid 4215 4216 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "MediaType"))) { 4217 media_type = ds->value; 4218 } 4219 else{ 4220 Cdbg(DBE, "No value 'MediaType' specified!"); 4221 con->http_status = 207; 4222 con->file_finished = 1; 4223 return HANDLER_FINISHED; 4224 } 4225 4226 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Start"))) { 4227 start = ds->value; 4228 } 4229 4230 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "End"))) { 4231 end = ds->value; 4232 } 4233 4234 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Keyword"))) { 4235 keyword = ds->value; 4236 } 4237 4238 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Orderby"))) { 4239 orderby = ds->value; 4240 } 4241 4242 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Orderrule"))) { 4243 orderrule = ds->value; 4244 } 4245 4246 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Parentid"))) { 4247 parentid = ds->value; 4248 } 4249 4250 get_minidlna_db_path(p); 4251 4252 if (!buffer_is_empty(p->minidlna_db_file)) { 4253 if (SQLITE_OK != sqlite3_open(p->minidlna_db_file->ptr, &(sql_minidlna))) { 4254 Cdbg(DBE, "Fail to open minidlna db %s", p->minidlna_db_file->ptr); 4255 } 4256 } 4257 4258 if (!sql_minidlna) { 4259 Cdbg(DBE, "NULL value 'sql_minidlna'!"); 4260 con->http_status = 207; 4261 con->file_finished = 1; 4262 return HANDLER_FINISHED; 4263 } 4264 4265 int rows, i; 4266 char **result; 4267 sqlite_int64 plID; 4268 char *plpath, *plname, *thumbnail, *resolution; 4269 char sql_query[2048] = "\0"; 4270 4271 int column_count = 7; 4272 sprintf(sql_query, "SELECT d.ID as ID, " 4273 "d.PATH as PATH, " 4274 "d.TITLE as TITLE, " 4275 "d.SIZE as SIZE, " 4276 "d.TIMESTAMP as TIMESTAMP, " 4277 "d.THUMBNAIL as THUMBNAIL, " 4278 "d.RESOLUTION as RESOLUTION " 4279 "from DETAILS d "); 4280 4281 if(!buffer_is_empty(parentid)){ 4282 sprintf(sql_query, "%s left join OBJECTS o on (o.DETAIL_ID = d.ID)", sql_query); 4283 } 4284 4285 if( buffer_is_equal_string(media_type, CONST_STR_LEN("1")) ){ 4286 sprintf(sql_query, "%s where d.MIME glob 'i*'", sql_query); 4287 } 4288 else if( buffer_is_equal_string(media_type, CONST_STR_LEN("2")) ){ 4289 sprintf(sql_query, "%s where d.MIME glob 'a*'", sql_query); 4290 } 4291 else if( buffer_is_equal_string(media_type, CONST_STR_LEN("3")) ){ 4292 sprintf(sql_query, "%s where d.MIME glob 'v*'", sql_query); 4293 } 4294 else if( buffer_is_equal_string(media_type, CONST_STR_LEN("0")) ){ 4295 sprintf(sql_query, "%s where d.MIME glob 'i*' or d.MIME glob 'a*' or d.MIME glob 'v*'", sql_query); 4296 } 4297 4298 #if 0 4299 if(!buffer_is_empty(keyword)){ 4300 buffer_urldecode_path(keyword); 4301 sprintf(sql_query, "%s and ( PATH LIKE '%s%s%s' or TITLE LIKE '%s%s%s' )", sql_query, "%", keyword->ptr, "%", "%", keyword->ptr, "%"); 4302 } 4303 #else 4304 if(!buffer_is_empty(keyword)){ 4305 buffer_urldecode_path(keyword); 4306 4307 if(strstr(keyword->ptr, "*")||strstr(keyword->ptr, "?")){ 4308 char buff[4096]; 4309 char* tmp = replace_str(keyword->ptr, "*", "%", (char *)&buff[0]); 4310 tmp = replace_str(tmp, "?", "_", (char *)&buff[0]); 4311 4312 sprintf(sql_query, "%s and ( PATH LIKE '%s' or TITLE LIKE '%s' )", sql_query, tmp, tmp); 4313 } 4314 else 4315 sprintf(sql_query, "%s and ( PATH LIKE '%s%s%s' or TITLE LIKE '%s%s%s' )", sql_query, "%", keyword->ptr, "%", "%", keyword->ptr, "%"); 4316 } 4317 #endif 4318 4319 if(!buffer_is_empty(parentid)){ 4320 sprintf(sql_query, "%s and o.PARENT_ID='%s'", sql_query, parentid->ptr ); 4321 } 4322 4323#if EMBEDDED_EANBLE 4324 //- Get mount partition 4325 char* disk_path = "/mnt/"; 4326 //DIR *dir; 4327 if (NULL != (dir = opendir(disk_path))) { 4328 struct dirent *de; 4329 while(NULL != (de = readdir(dir))) { 4330 if ( de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0' ) { 4331 continue; 4332 //- ignore the parent dir 4333 } 4334 4335 if ( de->d_name[0] == '.' ) { 4336 continue; 4337 //- ignore the hidden file 4338 } 4339 4340 char partion_path[100] = "\0"; 4341 sprintf(partion_path, "%s%s", disk_path, de->d_name); 4342 4343 //if(strstr( con->physical.path->ptr, partion_path ) && buffer_is_empty(parentid)){ 4344 if(strstr( con->physical.path->ptr, partion_path )){ 4345 sprintf(sql_query, "%s and PATH LIKE '%s%s/%s'", sql_query, "%", partion_path, "%"); 4346 break; 4347 } 4348 } 4349 closedir(dir); 4350 } 4351#endif 4352 4353 Cdbg(DBE, "1. sql_query=%s", sql_query); 4354 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) != SQLITE_OK ){ 4355 sqlite3_close(sql_minidlna); 4356 con->http_status = 207; 4357 con->file_finished = 1; 4358 Cdbg(DBE, "Fail to sql_get_table"); 4359 return HANDLER_FINISHED; 4360 } 4361 #if 0 4362 if( !rows ){ 4363 sqlite3_free_table(result); 4364 sqlite3_close(sql_minidlna); 4365 con->http_status = 207; 4366 con->file_finished = 1; 4367 Cdbg(DBE, "rows = 0!"); 4368 return HANDLER_FINISHED; 4369 } 4370 #endif 4371 //////////////////////////////////////////////////////////////////////////////////// 4372 4373 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 4374 4375 b = buffer_init(); 4376 4377 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")); 4378 buffer_append_string_len(b,CONST_STR_LEN("<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\" ")); 4379 4380 //- Total count 4381 buffer_append_string_len(b, CONST_STR_LEN(" qcount=\"")); 4382 char qcount[1024]="\0"; 4383 sprintf(qcount, "%d", rows); 4384 buffer_append_string(b, qcount); 4385 buffer_append_string_len(b, CONST_STR_LEN("\"")); 4386 4387 buffer_append_string_len(b, CONST_STR_LEN(" scan_status=\"")); 4388#if EMBEDDED_EANBLE 4389 //- Get scan status 4390 char dms_scanfile[64]; 4391 FILE *fp; 4392 4393 if (!buffer_is_empty(p->minidlna_db_dir)) { 4394 sprintf(dms_scanfile, "%s/scantag", p->minidlna_db_dir->ptr); 4395 4396 fp = fopen(dms_scanfile, "r"); 4397 4398 if(fp) { 4399 buffer_append_string(b, "Scanning"); 4400 fclose(fp); 4401 } 4402 else 4403 buffer_append_string(b, "Idle"); 4404 } 4405#else 4406 buffer_append_string(b, "Scanning"); 4407#endif 4408 buffer_append_string_len(b, CONST_STR_LEN("\"")); 4409 4410 int query_again = 0; 4411 if(!buffer_is_empty(orderby)){ 4412 if(!buffer_is_empty(orderrule)) 4413 sprintf(sql_query, "%s ORDER BY %s %s", sql_query, orderby->ptr, orderrule->ptr); 4414 else 4415 sprintf(sql_query, "%s ORDER BY %s ASC", sql_query, orderby->ptr); 4416 4417 query_again = 1; 4418 } 4419 4420 if(!buffer_is_empty(start) && !buffer_is_empty(end)){ 4421 sprintf(sql_query, "%s LIMIT %s, %s", sql_query, start->ptr, end->ptr); 4422 query_again = 1; 4423 4424 //- Start Index 4425 buffer_append_string_len(b, CONST_STR_LEN(" qstart=\"")); 4426 buffer_append_string_buffer(b, start); 4427 buffer_append_string_len(b, CONST_STR_LEN("\"")); 4428 4429 //- End Index 4430 int query_end = atoi(end->ptr); 4431 if( query_end > rows) query_end = rows; 4432 buffer_append_string_len(b, CONST_STR_LEN(" qend=\"")); 4433 char qend[1024]="\0"; 4434 sprintf(qend, "%d", query_end); 4435 buffer_append_string(b, qend); 4436 buffer_append_string_len(b, CONST_STR_LEN("\"")); 4437 } 4438 4439 Cdbg(DBE, "sql_query=%s, qcount=%s", sql_query, qcount); 4440 4441 buffer_append_string_len(b,CONST_STR_LEN(">\n")); 4442 4443 if(query_again==1){ 4444 sqlite3_free_table(result); 4445 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) != SQLITE_OK ){ 4446 sqlite3_close(sql_minidlna); 4447 con->http_status = 207; 4448 con->file_finished = 1; 4449 Cdbg(DBE, "Fail to sql_get_table 2"); 4450 return HANDLER_FINISHED; 4451 } 4452 } 4453 4454 Cdbg(DBE, "rows=%d", rows); 4455 4456 rows++; 4457 4458 char* usbdisk_name; 4459#if EMBEDDED_EANBLE 4460 char *a = nvram_get_productid(); 4461 int l = strlen(a)+1; 4462 usbdisk_name = (char*)malloc(l); 4463 memset(usbdisk_name,'\0', l); 4464 strcpy(usbdisk_name, a); 4465 #ifdef APP_IPKG 4466 free(a); 4467 #endif 4468#else 4469 usbdisk_name = (char*)malloc(8); 4470 memset(usbdisk_name,'\0', 8); 4471 strcpy(usbdisk_name, "usbdisk"); 4472#endif 4473 4474 /* allprop */ 4475 prop_200 = buffer_init(); 4476 prop_404 = buffer_init(); 4477 physical d; 4478 d.path = buffer_init(); 4479 d.rel_path = buffer_init(); 4480 4481 for( i=column_count; i<rows*column_count; i+=column_count ){ 4482 4483 //- ID, PATH, TITLE, SIZE, TIMESTAMP, THUMBNAIL 4484 plID = strtoll(result[i], NULL, 10); 4485 plpath = result[i+1]; 4486 plname = result[i+2]; 4487 thumbnail = result[i+5]; 4488 resolution = result[i+6]; 4489 4490 if(!plpath) 4491 continue; 4492 4493 int thumb = atoi(thumbnail); 4494 4495 if(thumb){ 4496 //Cdbg(DBE, "plpath=%s, thumbnail = %d, resolution = %s", plpath, atoi(thumbnail), resolution); 4497 4498 #ifdef USE_LIBEXIF 4499 ExifLoader *l = exif_loader_new(); 4500 exif_loader_write_file(l, plpath); 4501 ExifData *ed = exif_loader_get_data(l); 4502 exif_loader_unref(l); 4503 4504 if( ed ){ 4505 //Cdbg(DBE, "success"); 4506 4507 #if 0 4508 /* Make sure the image had a thumbnail before trying to write it */ 4509 if (ed->data && ed->size) { 4510 FILE *thumb; 4511 char thumb_name[1024]; 4512 4513 /* Try to create a unique name for the thumbnail file */ 4514 snprintf(thumb_name, sizeof(thumb_name), 4515 "%s_thumb.jpg", plpath); 4516 4517 thumb = fopen(thumb_name, "wb"); 4518 if (thumb) { 4519 /* Write the thumbnail image to the file */ 4520 fwrite(ed->data, 1, ed->size, thumb); 4521 fclose(thumb); 4522 Cdbg(DBE, "Wrote thumbnail to %s\n", thumb_name); 4523 } else { 4524 Cdbg(DBE, "Could not create file %s\n", thumb_name); 4525 } 4526 } else { 4527 Cdbg(DBE, "No EXIF thumbnail in file\n"); 4528 } 4529 #endif 4530 4531 /* Free the EXIF data */ 4532 exif_data_unref(ed); 4533 } 4534 #endif 4535 } 4536 4537 char buff[4096]; 4538 #if EMBEDDED_EANBLE 4539 char* tmp = replace_str(&plpath[0], 4540 "tmp/mnt", 4541 usbdisk_name, 4542 (char *)&buff[0]); 4543 #else 4544 char* tmp = replace_str(&plpath[0], 4545 "mnt", 4546 usbdisk_name, 4547 (char *)&buff[0]); 4548 4549 #endif 4550 4551 //Cdbg(DBE, "tmp=%s, con->url.path=%s", tmp, con->url.path->ptr); 4552 4553 buffer_copy_string(d.path, plpath); 4554 buffer_copy_string(d.rel_path, plpath); 4555 4556 buffer_reset(prop_200); 4557 buffer_reset(prop_404); 4558 4559 //Cdbg(DBE, "d.path=%s", d.path->ptr); 4560 //Cdbg(DBE, "d.rel_path=%s", d.rel_path->ptr); 4561 4562 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404); 4563 4564 buffer_append_string_len(b,CONST_STR_LEN("<D:response>\n")); 4565 buffer_append_string_len(b,CONST_STR_LEN("<D:href>")); 4566 buffer_append_string_buffer(b, con->uri.scheme); 4567 buffer_append_string_len(b,CONST_STR_LEN("://")); 4568 buffer_append_string_buffer(b, con->uri.authority); 4569 buffer_append_string_encoded(b, tmp, strlen(tmp), ENCODING_REL_URI); 4570 buffer_append_string_len(b,CONST_STR_LEN("</D:href>\n")); 4571 4572 if (!buffer_is_empty(prop_200)) { 4573 buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n")); 4574 buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n")); 4575 buffer_append_string_buffer(b, prop_200); 4576 buffer_append_string_len(b, CONST_STR_LEN("<D:title>")); 4577 buffer_append_string(b, plname); 4578 buffer_append_string_len(b, CONST_STR_LEN("</D:title>")); 4579 buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n")); 4580 buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 200 OK</D:status>\n")); 4581 buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n")); 4582 } 4583 if (!buffer_is_empty(prop_404)) { 4584 buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n")); 4585 buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n")); 4586 buffer_append_string_buffer(b, prop_404); 4587 4588 //- for test 4589 buffer_append_string_len(b, CONST_STR_LEN("<D:mtitle>")); 4590 buffer_append_string(b, plname); 4591 buffer_append_string_len(b, CONST_STR_LEN("</D:mtitle>")); 4592 4593 buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n")); 4594 buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 404 Not Found</D:status>\n")); 4595 buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n")); 4596 } 4597 4598 buffer_append_string_len(b,CONST_STR_LEN("</D:response>\n")); 4599 4600 } 4601 4602 buffer_free(d.path); 4603 buffer_free(d.rel_path); 4604 4605 buffer_free(prop_200); 4606 buffer_free(prop_404); 4607 4608 buffer_append_string_len(b,CONST_STR_LEN("</D:multistatus>\n")); 4609 4610 sqlite3_free_table(result); 4611 /* 4612 //- test 4613 Cdbg(DBE, "------------------------------"); 4614 4615 //- �M�� 4616 column_count = 4; 4617 //sprintf(sql_query, "SELECT PATH, TITLE, ALBUM_ART, ARTIST from DETAILS where TITLE='- All Albums -'"); 4618 sprintf(sql_query, "SELECT d.PATH as PATH, " 4619 "d.TITLE as TITLE, " 4620 "d.ALBUM_ART as ALBUM_ART, " 4621 "d.ARTIST as ARTIST " 4622 "from OBJECTS o " 4623 "left join DETAILS d on (o.DETAIL_ID = d.ID)" 4624 " where o.CLASS = 'container.album.musicAlbum'"); 4625 4626 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 4627 Cdbg(DBE, "sql_query=%s, rows=%d", sql_query, rows); 4628 int i=0; 4629 for( i=column_count; i<rows*column_count; i+=column_count ){ 4630 4631 Cdbg(DBE, "1, i=%d, PATH=%s, TITLE=%s, ALBUM_ART=%s, ARTIST=%s", 4632 i, result[i], result[i+1], result[i+2], result[i+3]); 4633 } 4634 4635 sqlite3_free_table(result); 4636 } 4637 4638 //- �t���� 4639 column_count = 4; 4640 //sprintf(sql_query, "SELECT PATH, TITLE, ALBUM_ART, ARTIST from DETAILS where TITLE='- All Albums -'"); 4641 sprintf(sql_query, "SELECT d.PATH as PATH, d.TITLE as TITLE, d.ALBUM_ART as ALBUM_ART, d.ARTIST as ARTIST from OBJECTS o " 4642 "left join DETAILS d on (o.DETAIL_ID = d.ID)" 4643 " where o.CLASS = 'container.person.musicArtist'"); 4644 4645 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 4646 Cdbg(DBE, "sql_query=%s, rows=%d", sql_query, rows); 4647 int i=0; 4648 for( i=column_count; i<rows*column_count; i+=column_count ){ 4649 4650 Cdbg(DBE, "2, i=%d, PATH=%s, TITLE=%s, ALBUM_ART=%s, ARTIST=%s", 4651 i, result[i], result[i+1], result[i+2], result[i+3]); 4652 } 4653 4654 sqlite3_free_table(result); 4655 } 4656 4657 column_count = 4; 4658 sprintf(sql_query, "SELECT PATH, TITLE, ALBUM_ART, ARTIST from DETAILS"); 4659 Cdbg(DBE, "sql_query=%s", sql_query); 4660 4661 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 4662 4663 int i=0; 4664 for( i=column_count; i<rows*column_count; i+=column_count ){ 4665 4666 4667 Cdbg(DBE, "nbbb, i=%d, PATH=%s, TITLE=%s, ALBUM_ART=%s, ARTIST=%s", 4668 i, result[i], result[i+1], result[i+2], result[i+3]); 4669 } 4670 4671 sqlite3_free_table(result); 4672 } 4673 4674 4675 column_count = 5; 4676 sprintf(sql_query, "SELECT NAME, CLASS, OBJECT_ID, PARENT_ID, REF_ID from OBJECTS"); 4677 4678 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 4679 Cdbg(DBE, "sql_query=%s, rows=%d", sql_query, rows); 4680 int i=0; 4681 for( i=column_count; i<rows*column_count; i+=column_count ){ 4682 Cdbg(DBE, "nccc, i=%d, NAME=%s, OBJECT_ID=%s, PARENT_ID=%s, REF_ID=%s", 4683 i, result[i], result[i+2], result[i+3], result[i+4]); 4684 } 4685 4686 sqlite3_free_table(result); 4687 } 4688 4689 4690 column_count = 1; 4691 sprintf(sql_query, "SELECT PATH from ALBUM_ART"); 4692 if( sql_get_table(sql_minidlna, sql_query, &result2, &rows2, NULL) == SQLITE_OK ){ 4693 Cdbg(DBE, "sql_query=%s, rows=%d", sql_query, rows2); 4694 int i=0; 4695 for( i=column_count; i<rows2*column_count; i+=column_count ){ 4696 //sqlite_int64 plID = strtoll(result[i], NULL, 10); 4697 //char* plpath = result[i+1]; 4698 //Cdbg(DBE, "nddd, i=%d, ID=%lld, PATH=%s", i, plID, plpath); 4699 4700 char* plpath = result2[i]; 4701 Cdbg(DBE, "nddd, i=%d, PATH=%s", i, plpath); 4702 } 4703 } 4704 4705 sqlite3_free_table(result2); 4706 //sqlite3_close(sql_minidlna); 4707 4708 4709 Cdbg(DBE, "------------------------------"); 4710 */ 4711 4712 sqlite3_close(sql_minidlna); 4713#endif 4714 chunkqueue_append_buffer(con->write_queue, b); 4715 buffer_free(b); 4716 4717 con->http_status = 207; 4718 con->file_finished = 1; 4719 return HANDLER_FINISHED; 4720 } 4721 4722 case HTTP_METHOD_GETMUSICCLASSIFICATION:{ 4723 Cdbg(DBE, "do HTTP_METHOD_GETMUSICCLASSIFICATION"); 4724 4725#if EMBEDDED_EANBLE 4726 if(!con->srv_socket->is_ssl){ 4727 con->http_status = 403; 4728 return HANDLER_FINISHED; 4729 } 4730#endif 4731 4732 if(is_dms_enabled() == 0){ 4733 //- Service Not Available 4734 con->http_status = 503; 4735 return HANDLER_FINISHED; 4736 } 4737 4738 buffer* classify = NULL; 4739 4740 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Classify"))) { 4741 classify = ds->value; 4742 } 4743 else{ 4744 con->http_status = 400; 4745 con->file_finished = 1; 4746 return HANDLER_FINISHED; 4747 } 4748 4749#ifdef USE_MINIDLNA_DB 4750 sqlite3 *sql_minidlna = NULL; 4751 if (!buffer_is_empty(p->minidlna_db_file)) { 4752 if (SQLITE_OK != sqlite3_open(p->minidlna_db_file->ptr, &(sql_minidlna))) { 4753 Cdbg(DBE, "Fail to open minidlna db %s", p->minidlna_db_file->ptr); 4754 } 4755 } 4756 4757 if (!sql_minidlna) { 4758 Cdbg(DBE, "NULL value 'sql_minidlna'!"); 4759 con->http_status = 207; 4760 con->file_finished = 1; 4761 return HANDLER_FINISHED; 4762 } 4763 4764 int column_count = 5; 4765 int rows, i; 4766 char **result; 4767 char sql_query[2048] = "\0"; 4768 4769 if(buffer_is_equal_string(classify, CONST_STR_LEN("album"))){ 4770 sprintf(sql_query, "SELECT d.TITLE as TITLE, " 4771 "d.ALBUM_ART as ALBUM_ART, " 4772 "d.ARTIST as ARTIST, " 4773 "o.PARENT_ID as PARENT_ID, " 4774 "o.OBJECT_ID as OBJECT_ID " 4775 "from OBJECTS o " 4776 "left join DETAILS d on (o.DETAIL_ID = d.ID) " 4777 "where o.CLASS = 'container.album.musicAlbum' " 4778 "and o.PARENT_ID = '%s'", MUSIC_ALBUM_ID); 4779 } 4780 else if(buffer_is_equal_string(classify, CONST_STR_LEN("artist"))){ 4781 sprintf(sql_query, "SELECT d.TITLE as TITLE, " 4782 "d.ALBUM_ART as ALBUM_ART, " 4783 "d.ARTIST as ARTIST, " 4784 "o.PARENT_ID as PARENT_ID, " 4785 "o.OBJECT_ID as OBJECT_ID " 4786 "from OBJECTS o " 4787 "left join DETAILS d on (o.DETAIL_ID = d.ID) " 4788 "where o.CLASS = 'container.person.musicArtist'" 4789 "and o.PARENT_ID = '%s'", MUSIC_ARTIST_ID); 4790 } 4791 else{ 4792 con->http_status = 400; 4793 con->file_finished = 1; 4794 sqlite3_close(sql_minidlna); 4795 return HANDLER_FINISHED; 4796 } 4797 4798 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 4799 4800 b = buffer_init(); 4801 4802 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>")); 4803 buffer_append_string_len(b,CONST_STR_LEN("<result>")); 4804 4805 Cdbg(DBE, "do HTTP_METHOD_GETMUSICCLASSIFICATION, sql_query=%s", sql_query); 4806 4807 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 4808 Cdbg(DBE, "sql_query=%s, rows=%d", sql_query, rows); 4809 int i=0; 4810 4811 for( i=column_count; i<=rows*column_count; i+=column_count ){ 4812 4813 char* title = result[i]; 4814 char* album_art = result[i+1]; 4815 char* artist = result[i+2]; 4816 char* parent_id = result[i+3]; 4817 char* object_id = result[i+4]; 4818 4819 buffer* id = buffer_init(); 4820 buffer_copy_string(id,object_id); 4821 if(buffer_is_equal_string(classify, CONST_STR_LEN("artist"))) 4822 buffer_append_string(id,"$0"); 4823 4824 Cdbg(DBE, "1, TITLE=%s, ALBUM_ART=%s, ARTIST=%s", title, album_art, artist); 4825 4826#if 1 4827 int column_count2 = 1; 4828 int rows2, j; 4829 char **result2; 4830 int partion_count = 0; 4831 4832 sprintf(sql_query, "SELECT COUNT(*) as COUNT from DETAILS d " 4833 "LEFT JOIN OBJECTS o on (o.DETAIL_ID = d.ID) " 4834 "WHERE d.MIME glob 'a*' AND o.PARENT_ID='%s' ", id->ptr); 4835 4836#if EMBEDDED_EANBLE 4837 //- Get mount partition 4838 char* disk_path = "/mnt/"; 4839 char partion_path[100] = "\0"; 4840 //DIR *dir; 4841 if (NULL != (dir = opendir(disk_path))) { 4842 struct dirent *de; 4843 while(NULL != (de = readdir(dir))) { 4844 if ( de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0' ) { 4845 continue; 4846 //- ignore the parent dir 4847 } 4848 4849 if ( de->d_name[0] == '.' ) { 4850 continue; 4851 //- ignore the hidden file 4852 } 4853 4854 sprintf(partion_path, "%s%s", disk_path, de->d_name); 4855 4856 if(strstr( con->physical.path->ptr, partion_path )){ 4857 sprintf(sql_query, "%s AND PATH LIKE '%s%s/%s'", sql_query, "%", partion_path, "%"); 4858 } 4859 4860 partion_count++; 4861 } 4862 closedir(dir); 4863 } 4864#else 4865 char partion_path[100] = "/mnt/sda"; 4866 sprintf(sql_query, "%s AND PATH LIKE '%s%s/%s'", sql_query, "%", partion_path, "%"); 4867 partion_count = 1; 4868#endif 4869 if(partion_count>1){ 4870 Cdbg(1, "sql_query=%s", sql_query); 4871 int count = 0; 4872 if( sql_get_table(sql_minidlna, sql_query, &result2, &rows2, NULL) == SQLITE_OK ){ 4873 Cdbg(DBE, "aaaaaaaaaaaaaa rows2=%d", rows2); 4874 4875 for( j=column_count2; j<=rows2*column_count2; j+=column_count2 ){ 4876 count = atoi(result2[j]); 4877 } 4878 4879 sqlite3_free_table(result2); 4880 } 4881 4882 Cdbg(DBE, "bbbbbbbbbbbbb count=%d", count); 4883 4884 if(count==0){ 4885 buffer_free(id); 4886 continue; 4887 } 4888 } 4889#endif 4890 4891 buffer_append_string_len(b,CONST_STR_LEN("<item>")); 4892 buffer_append_string_len(b,CONST_STR_LEN("<id>")); 4893 //buffer_append_string(b,object_id); 4894 //if(buffer_is_equal_string(classify, CONST_STR_LEN("artist"))) 4895 // buffer_append_string(b,"$0"); 4896 buffer_append_string_buffer(b, id); 4897 buffer_append_string_len(b,CONST_STR_LEN("</id>")); 4898 buffer_append_string_len(b,CONST_STR_LEN("<title>")); 4899 buffer_append_string(b,title); 4900 buffer_append_string_len(b,CONST_STR_LEN("</title>")); 4901 buffer_append_string_len(b,CONST_STR_LEN("<artist>")); 4902 buffer_append_string(b,artist); 4903 buffer_append_string_len(b,CONST_STR_LEN("</artist>")); 4904 4905 char* image = NULL; 4906 sqlite_int64 plAlbumArt = (album_art ? strtoll(album_art, NULL, 10) : 0); 4907 if(get_album_cover_image(sql_minidlna, plAlbumArt, &image)==1){ 4908 buffer_append_string_len(b, CONST_STR_LEN("<thumb_image>")); 4909 buffer_append_string(b, image); 4910 buffer_append_string_len(b, CONST_STR_LEN("</thumb_image>")); 4911 free(image); 4912 } 4913 4914 buffer_append_string_len(b,CONST_STR_LEN("</item>")); 4915 4916 buffer_free(id); 4917 } 4918 4919 sqlite3_free_table(result); 4920 } 4921 4922 sqlite3_close(sql_minidlna); 4923 buffer_append_string_len(b,CONST_STR_LEN("</result>")); 4924#endif 4925 4926 chunkqueue_append_buffer(con->write_queue, b); 4927 buffer_free(b); 4928 4929 con->http_status = 200; 4930 con->file_finished = 1; 4931 return HANDLER_FINISHED; 4932 } 4933 4934 case HTTP_METHOD_GETMUSICPLAYLIST:{ 4935 Cdbg(DBE, "do HTTP_METHOD_GETMUSICPLAYLIST"); 4936#if EMBEDDED_EANBLE 4937 if(!con->srv_socket->is_ssl){ 4938 con->http_status = 403; 4939 return HANDLER_FINISHED; 4940 } 4941#endif 4942 4943 if(is_dms_enabled() == 0){ 4944 //- Service Not Available 4945 con->http_status = 503; 4946 return HANDLER_FINISHED; 4947 } 4948 4949 buffer* play_id = NULL; 4950 4951 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "id"))) { 4952 play_id = ds->value; 4953 } 4954 else{ 4955 con->http_status = 400; 4956 con->file_finished = 1; 4957 return HANDLER_FINISHED; 4958 } 4959#ifdef USE_MINIDLNA_DB 4960 sqlite3 *sql_minidlna = NULL; 4961 if (!buffer_is_empty(p->minidlna_db_file)) { 4962 if (SQLITE_OK != sqlite3_open(p->minidlna_db_file->ptr, &(sql_minidlna))) { 4963 Cdbg(DBE, "Fail to open minidlna db %s", p->minidlna_db_file->ptr); 4964 } 4965 } 4966 4967 if (!sql_minidlna) { 4968 Cdbg(DBE, "NULL value 'sql_minidlna'!"); 4969 con->http_status = 207; 4970 con->file_finished = 1; 4971 return HANDLER_FINISHED; 4972 } 4973 4974 int column_count = 2; 4975 int rows, i; 4976 char **result; 4977 char sql_query[2048] = "\0"; 4978 4979 sprintf(sql_query, "SELECT d.TITLE as TITLE, " 4980 "d.PATH as PATH " 4981 "from OBJECTS o " 4982 "left join DETAILS d on (o.DETAIL_ID = d.ID) " 4983 "where o.PARENT_ID = '%s'", play_id->ptr); 4984 4985 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 4986 4987 b = buffer_init(); 4988 4989 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>")); 4990 buffer_append_string_len(b,CONST_STR_LEN("<result>")); 4991 4992 Cdbg(DBE, "do HTTP_METHOD_GETMUSICPLAYLIST, sql_query=%s", sql_query); 4993 4994 char auth[100]="\0"; 4995 if(con->aidisk_username->used && con->aidisk_passwd->used) 4996 sprintf(auth, "%s:%s", con->aidisk_username->ptr, con->aidisk_passwd->ptr); 4997 else{ 4998 con->http_status = 400; 4999 sqlite3_close(sql_minidlna); 5000 return HANDLER_FINISHED; 5001 } 5002 5003 char* base64_auth = ldb_base64_encode(auth, strlen(auth)); 5004 5005 if( sql_get_table(sql_minidlna, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 5006 Cdbg(DBE, "sql_query=%s, rows=%d", sql_query, rows); 5007 int i=0; 5008 5009 for( i=column_count; i<=rows*column_count; i+=column_count ){ 5010 5011 char* title = result[i]; 5012 char* path = result[i+1]; 5013 Cdbg(DBE, "title=%s", title); 5014 Cdbg(DBE, "path=%s", path); 5015 buffer_append_string_len(b,CONST_STR_LEN("<item>")); 5016 buffer_append_string_len(b,CONST_STR_LEN("<title>")); 5017 if(title) buffer_append_string(b,title); 5018 buffer_append_string_len(b,CONST_STR_LEN("</title>")); 5019 buffer_append_string_len(b,CONST_STR_LEN("<path>")); 5020 if(path) buffer_append_string(b,path); 5021 buffer_append_string_len(b,CONST_STR_LEN("</path>")); 5022 5023 if(path){ 5024 char* filename = NULL; 5025 buffer* buffer_filename = buffer_init(); 5026 extract_filename(path, &filename); 5027 buffer_copy_string(buffer_filename, ""); 5028 buffer_append_string_encoded(buffer_filename,filename,strlen(filename),ENCODING_REL_URI); 5029 free(filename); 5030 5031 char* filepath = NULL; 5032 extract_filepath(path, &filepath); 5033 5034 char buff[4096]; 5035 char* usbdisk_name; 5036 5037 #if EMBEDDED_EANBLE 5038 char *a = nvram_get_productid(); 5039 int l = strlen(a)+1; 5040 usbdisk_name = (char*)malloc(l); 5041 memset(usbdisk_name,'\0', l); 5042 strcpy(usbdisk_name, a); 5043 #ifdef APP_IPKG 5044 free(a); 5045 #endif 5046 char* tmp = replace_str(&filepath[0], 5047 "tmp/mnt", 5048 usbdisk_name, 5049 (char *)&buff[0]); 5050 #else 5051 usbdisk_name = (char*)malloc(8); 5052 memset(usbdisk_name,'\0', 8); 5053 strcpy(usbdisk_name, "usbdisk"); 5054 char* tmp = replace_str(&filepath[0], 5055 "mnt", 5056 usbdisk_name, 5057 (char *)&buff[0]); 5058 5059 #endif 5060 5061 buffer* buffer_filepath = buffer_init(); 5062 buffer_copy_string(buffer_filepath, ""); 5063 buffer_append_string_encoded(buffer_filepath,tmp,strlen(tmp),ENCODING_REL_URI); 5064 5065 Cdbg(DBE, "filename=%s, filepath=%s", buffer_filename->ptr, buffer_filepath->ptr); 5066 5067 buffer* buffer_result_share_link; 5068 if( generate_sharelink(srv, 5069 con, 5070 buffer_filename->ptr, 5071 buffer_filepath->ptr, 5072 base64_auth, 0, 0, 5073 &buffer_result_share_link) == 1){ 5074 buffer_append_string_len(b,CONST_STR_LEN("<sharelink>")); 5075 Cdbg(DBE, "sharelink=%s", buffer_result_share_link->ptr); 5076 buffer_append_string_buffer(b,buffer_result_share_link); 5077 buffer_append_string_len(b,CONST_STR_LEN("</sharelink>")); 5078 } 5079 5080 free(usbdisk_name); 5081 free(filepath); 5082 buffer_free(buffer_filename); 5083 buffer_free(buffer_filepath); 5084 buffer_free(buffer_result_share_link); 5085 } 5086 5087 buffer_append_string_len(b,CONST_STR_LEN("</item>")); 5088 } 5089 5090 sqlite3_free_table(result); 5091 } 5092 5093 sqlite3_close(sql_minidlna); 5094 free(base64_auth); 5095 5096 buffer_append_string_len(b,CONST_STR_LEN("</result>")); 5097#endif 5098 5099 //Cdbg(DBE, "b=%s", b->ptr); 5100 chunkqueue_append_buffer(con->write_queue, b); 5101 buffer_free(b); 5102 5103 con->http_status = 200; 5104 con->file_finished = 1; 5105 return HANDLER_FINISHED; 5106 } 5107 5108 case HTTP_METHOD_GETTHUMBIMAGE:{ 5109 Cdbg(DBE, "do HTTP_METHOD_GETTHUMBIMAGE"); 5110 5111#if EMBEDDED_EANBLE 5112 if(!con->srv_socket->is_ssl){ 5113 con->http_status = 403; 5114 return HANDLER_FINISHED; 5115 } 5116#endif 5117 5118 if(is_dms_enabled() == 0){ 5119 //- Service Not Available 5120 con->http_status = 503; 5121 return HANDLER_FINISHED; 5122 } 5123 5124 buffer* file = NULL; 5125 5126 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "File"))) { 5127 file = ds->value; 5128 } 5129 else{ 5130 con->http_status = 400; 5131 con->file_finished = 1; 5132 return HANDLER_FINISHED; 5133 } 5134 5135 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 5136 5137 b = buffer_init(); 5138 5139 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>")); 5140 buffer_append_string_len(b,CONST_STR_LEN("<result>")); 5141 5142 buffer* file_path = buffer_init(); 5143 buffer_copy_buffer(file_path, con->physical.path); 5144 buffer_append_string_len(file_path, CONST_STR_LEN("/")); 5145 buffer_append_string_buffer(file_path, file); 5146 5147 char* image = NULL; 5148 Cdbg(1, "file_path = %s", file_path->ptr); 5149 if(get_thumb_image(file_path->ptr, p, &image)==1){ 5150 buffer_append_string_len(b, CONST_STR_LEN("<thumb_image>")); 5151 buffer_append_string(b, image); 5152 buffer_append_string_len(b, CONST_STR_LEN("</thumb_image>")); 5153 free(image); 5154 } 5155 5156 buffer_append_string_len(b,CONST_STR_LEN("</result>")); 5157 5158 buffer_free(file_path); 5159 5160 chunkqueue_append_buffer(con->write_queue, b); 5161 buffer_free(b); 5162 5163 con->http_status = 200; 5164 con->file_finished = 1; 5165 return HANDLER_FINISHED; 5166 } 5167 5168 case HTTP_METHOD_GETVIDEOSUBTITLE:{ 5169#if EMBEDDED_EANBLE 5170 if(!con->srv_socket->is_ssl){ 5171 con->http_status = 403; 5172 return HANDLER_FINISHED; 5173 } 5174#endif 5175 5176 buffer* filename = NULL; 5177 5178 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "FILENAME"))) { 5179 filename = ds->value; 5180 } else { 5181 con->http_status = 400; 5182 return HANDLER_FINISHED; 5183 } 5184 5185 Cdbg(DBE, "do HTTP_METHOD_GETVIDEOSUBTITLE %s, filename=%s", con->physical.path->ptr, filename->ptr); 5186 5187 char auth[100]="\0"; 5188 if(con->aidisk_username->used && con->aidisk_passwd->used) 5189 sprintf(auth, "%s:%s", con->aidisk_username->ptr, con->aidisk_passwd->ptr); 5190 else{ 5191 con->http_status = 400; 5192 return HANDLER_FINISHED; 5193 } 5194 5195 char* base64_auth = ldb_base64_encode(auth, strlen(auth)); 5196 5197 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 5198 5199 b = buffer_init(); 5200 5201 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>")); 5202 buffer_append_string_len(b,CONST_STR_LEN("<result>")); 5203 5204 if (NULL != (dir = opendir(con->physical.path->ptr))) { 5205 struct dirent *de; 5206 5207 while(NULL != (de = readdir(dir))) { 5208 struct stat st; 5209 int status = 0; 5210 5211 if ((de->d_name[0] == '.' && de->d_name[1] == '\0') || 5212 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) { 5213 continue; 5214 /* ignore the parent dir */ 5215 } 5216 5217 char* aa = get_filename_ext(de->d_name); 5218 int len = strlen(aa)+1; 5219 char* file_ext = (char*)malloc(len); 5220 memset(file_ext,'\0', len); 5221 strcpy(file_ext, aa); 5222 for (int i = 0; file_ext[i]; i++) 5223 file_ext[i] = tolower(file_ext[i]); 5224 5225 if( strcmp(file_ext, "srt")==0 && 5226 strstr(de->d_name, filename->ptr)){ 5227 5228 #if 0 5229 #define BUF_LEN 256 5230 //char utf[1024] = "���������r��"; 5231 unsigned long uni2[BUF_LEN] = { 5232 0x8BF7, 0x4FDD, 0x8BC1, 0x8BE5, 0x6587, 0x4EF6, 0x662F, 0x4EE5, 5233 0x20, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x20, 0x683C, 0x5F0F, 5234 0x5B58, 0x50A8, 0x7684, 0x21, 0x0 5235 }; 5236 char utf2[BUF_LEN]; 5237 int utflen2 = BUF_LEN; 5238 int ret2 = enc_unicode_to_utf8_str(uni2, (unsigned char *)utf2, &utflen2); 5239 if ( ret2 == 1 ){ 5240 Cdbg(DBE, "Ooooooooooooooooooooooooooooooooooook!"); 5241 utf2[utflen2] = '\0'; 5242 Cdbg(DBE, "utf2=%s", utf2); 5243 } 5244 #endif 5245#if 0 5246 #define BUF_LEN 1024 5247 buffer* srt_file = buffer_init(); 5248 buffer_copy_buffer(srt_file, con->physical.path); 5249 buffer_append_string(srt_file, "/"); 5250 buffer_append_string(srt_file, de->d_name); 5251 Cdbg(DBE, "srt_file=%s", srt_file->ptr); 5252 5253 if(!is_utf8_file(srt_file->ptr)){ 5254 5255 buffer* new_srt_file = buffer_init(); 5256 5257 buffer_copy_buffer(new_srt_file, con->physical.path); 5258 buffer_append_string(new_srt_file, "/"); 5259 buffer_append_string_buffer(new_srt_file, filename); 5260 buffer_append_string(new_srt_file, "_utf8.srt"); 5261 5262 //buffer_append_string(new_srt_file, "/tmp/out.srt"); 5263 5264 Cdbg(DBE, "new_srt_file=%s", new_srt_file->ptr); 5265 5266 FILE* fp3, *fp4; 5267 char line[BUF_LEN]; 5268 5269 fp4 = fopen(new_srt_file->ptr, "w"); 5270 5271 //- write utf-8 file header 5272 unsigned char utf8_header[3] = {0xEF, 0xBB, 0xBF}; 5273 fputs(utf8_header,fp4); 5274 5275 if((fp3 = fopen(srt_file->ptr, "r")) != NULL){ 5276 5277 #if 1 5278 memset(line, 0, sizeof(line)); 5279 while(fgets(line, BUF_LEN, fp3) != NULL){ 5280 5281 //Cdbg(1, "line=%s", line); 5282 //- ANSI to UTF-8 5283 char *iconv_buf = (char*)calloc(BUF_LEN, sizeof(char)); 5284 5285 int rc = do_iconv("UTF-8", "CP950", 5286 line, 5287 strlen(line), 5288 iconv_buf, 5289 BUF_LEN); 5290 //Cdbg(1, "iconv_buf=%s", iconv_buf); 5291 fputs(iconv_buf,fp4); 5292 5293 free(iconv_buf); 5294 } 5295 #else 5296 setlocale(LC_ALL, ""); 5297 char line2[BUF_LEN]; 5298 while(fgets(line2, BUF_LEN, fp3) != NULL){ 5299 5300 //Cdbg(DBE, "line2=%s", line2); 5301 5302 char utf2[BUF_LEN]; 5303 int utflen2 = BUF_LEN; 5304 //char uni2[BUF_LEN] = "���������r��"; 5305 /* 5306 unsigned long uni2[BUF_LEN] = { 5307 0x8BF7, 0x4FDD, 0x8BC1, 0x8BE5, 0x6587, 0x4EF6, 0x662F, 0x4EE5, 5308 0x20, 0x75, 0x74, 0x66, 0x2D, 0x38, 0x20, 0x683C, 0x5F0F, 5309 0x5B58, 0x50A8, 0x7684, 0x21, 0x0 5310 }; 5311 */ 5312 5313 #if 0 5314 wchar_t wt1[BUF_LEN]; 5315 int size4 = ansiToWCHAR(wt1, BUF_LEN, line2 ,BUF_LEN+1, "en_ZW.utf8"); 5316 if(size4>0){ 5317 int ret2 = enc_unicode_to_utf8_str(wt1, (unsigned char *)utf2, &utflen2); 5318 if ( ret2 == 1 ){ 5319 utf2[utflen2] = '\0'; 5320 Cdbg(DBE, "utf2=%s", utf2); 5321 fputs(utf2,fp4); 5322 } 5323 } 5324 #else 5325 int ret2 = enc_unicode_to_utf8_str((unsigned long *)m2w(line2), (unsigned char *)utf2, &utflen2); 5326 if ( ret2 == 1 ){ 5327 utf2[utflen2] = '\0'; 5328 Cdbg(DBE, "utf2=%s", utf2); 5329 fputs(utf2,fp4); 5330 } 5331 #endif 5332 } 5333 #endif 5334 5335 fclose(fp3); 5336 } 5337 5338 physical s, d; 5339 5340 s.path = buffer_init(); 5341 s.rel_path = buffer_init(); 5342 buffer_copy_buffer(s.path, new_srt_file); 5343 5344 d.path = buffer_init(); 5345 d.rel_path = buffer_init(); 5346 buffer_copy_buffer(d.path,srt_file); 5347 5348 Cdbg(DBE, "copy=%s -> %s", new_srt_file->ptr, srt_file->ptr); 5349 5350 //webdav_copy_file(srv, con, p, &s, &d, 1); 5351 5352 fclose(fp4); 5353 buffer_free(srt_file); 5354 buffer_free(new_srt_file); 5355 } 5356 5357#endif 5358 buffer* buffer_filepath = buffer_init(); 5359 buffer_copy_string(buffer_filepath, ""); 5360 buffer_append_string_encoded(buffer_filepath, con->url.path->ptr, strlen(con->url.path->ptr), ENCODING_REL_URI); 5361 5362 buffer* buffer_result_share_link; 5363 if( generate_sharelink(srv, 5364 con, 5365 de->d_name, 5366 buffer_filepath->ptr, 5367 base64_auth, 0, 0, 5368 &buffer_result_share_link) == 1){ 5369 buffer_append_string_len(b,CONST_STR_LEN("<file>")); 5370 buffer_append_string_len(b,CONST_STR_LEN("<name>")); 5371 buffer_append_string(b,de->d_name); 5372 buffer_append_string_len(b,CONST_STR_LEN("</name>")); 5373 buffer_append_string_len(b,CONST_STR_LEN("<sharelink>")); 5374 buffer_append_string_buffer(b,buffer_result_share_link); 5375 buffer_append_string_len(b,CONST_STR_LEN("</sharelink>")); 5376 buffer_append_string_len(b,CONST_STR_LEN("</file>")); 5377 } 5378 5379 buffer_free(buffer_filepath); 5380 buffer_free(buffer_result_share_link); 5381 } 5382 5383 free(file_ext); 5384 } 5385 5386 closedir(dir); 5387 } 5388 5389 buffer_append_string_len(b,CONST_STR_LEN("</result>")); 5390 5391 chunkqueue_append_buffer(con->write_queue, b); 5392 buffer_free(b); 5393 5394 con->http_status = 200; 5395 con->file_finished = 1; 5396 return HANDLER_FINISHED; 5397 } 5398 5399 case HTTP_METHOD_UPLOADTOFACEBOOK:{ 5400 Cdbg(1, "do HTTP_METHOD_UPLOADTOFACEBOOK"); 5401 5402#if EMBEDDED_EANBLE 5403 if(!con->srv_socket->is_ssl){ 5404 con->http_status = 403; 5405 return HANDLER_FINISHED; 5406 } 5407#endif 5408 5409 buffer* filename = NULL; 5410 buffer* title = NULL; 5411 buffer* album = NULL; 5412 buffer* auth_token = NULL; 5413 5414 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "FILENAME"))) { 5415 filename = ds->value; 5416 buffer_urldecode_path(filename); 5417 } else { 5418 con->http_status = 400; 5419 return HANDLER_FINISHED; 5420 } 5421 5422 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TITLE"))) { 5423 title = ds->value; 5424 buffer_urldecode_path(title); 5425 } else { 5426 con->http_status = 400; 5427 return HANDLER_FINISHED; 5428 } 5429 5430 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TOKEN"))) { 5431 auth_token = ds->value; 5432 } else { 5433 con->http_status = 400; 5434 return HANDLER_FINISHED; 5435 } 5436 5437 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "ALBUM"))) { 5438 album = ds->value; 5439 } else { 5440 con->http_status = 400; 5441 return HANDLER_FINISHED; 5442 } 5443 5444 CURL *curl; 5445 CURLcode rt; 5446 struct curl_httppost *formpost = NULL; 5447 struct curl_httppost *lastptr = NULL; 5448 char md5[129]; 5449 char* response_str; 5450 char url_upload_facebook[1024] = "\0"; 5451 curl = curl_easy_init(); 5452 5453 strcpy(url_upload_facebook, "https://graph.facebook.com/"); 5454 strcat(url_upload_facebook, album->ptr); 5455 strcat(url_upload_facebook, "/photos"); 5456 5457 Cdbg(1, "url_upload_facebook=%s", url_upload_facebook); 5458 5459 if(curl) { 5460 Cdbg(1, "curl_easy_init OK"); 5461 5462 /* Set Host to target in HTTP header, and set response handler 5463 * function */ 5464 curl_easy_setopt(curl, CURLOPT_URL, url_upload_facebook); 5465 5466 5467 /* Build the form post */ 5468 curl_formadd(&formpost, &lastptr, 5469 CURLFORM_COPYNAME, "access_token", 5470 CURLFORM_COPYCONTENTS, auth_token->ptr, CURLFORM_END); 5471 5472 curl_formadd(&formpost, &lastptr, 5473 CURLFORM_COPYNAME, "message", 5474 CURLFORM_COPYCONTENTS, title->ptr, CURLFORM_END); 5475 5476 curl_formadd(&formpost, &lastptr, 5477 CURLFORM_COPYNAME, "status", 5478 CURLFORM_COPYCONTENTS, "success", CURLFORM_END); 5479 5480 char photo_path[1024] = "\0"; 5481 sprintf(photo_path, "%s/%s", con->physical.path->ptr, filename->ptr); 5482 Cdbg(1, "photo_path=%s", photo_path); 5483 5484 //- check file exists 5485 if(!file_exist(photo_path)){ 5486 curl_easy_cleanup(curl); 5487 curl_formfree(formpost); 5488 con->http_status = 404; 5489 return HANDLER_FINISHED; 5490 } 5491 5492 curl_formadd(&formpost, &lastptr, 5493 CURLFORM_COPYNAME, "source", 5494 CURLFORM_FILE, photo_path, CURLFORM_END); 5495 5496 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); 5497 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); 5498 5499 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); 5500 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_callback_func); 5501 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_str); 5502 5503 Cdbg(1, "Uploading..."); 5504 rt = curl_easy_perform(curl); 5505 5506 #if 1 5507 /* now extract transfer info */ 5508 double speed_upload, total_time; 5509 curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed_upload); 5510 curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time); 5511 5512 Cdbg(1, "Speed: %.3f bytes/sec during %.3f seconds, response_str=%s", 5513 speed_upload, total_time, response_str); 5514 5515 free(response_str); 5516 #else 5517 if (rt) { 5518 Cdbg(1, "An error occurred during upload! %s", curl_easy_strerror(rt)); 5519 } 5520 else{ 5521 /* now extract transfer info */ 5522 double speed_upload, total_time; 5523 curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed_upload); 5524 curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time); 5525 5526 Cdbg(1, "Speed: %.3f bytes/sec during %.3f seconds", 5527 speed_upload, total_time); 5528 } 5529 #endif 5530 5531 /* Done. Cleanup. */ 5532 curl_easy_cleanup(curl); 5533 curl_formfree(formpost); 5534 } 5535 5536 con->http_status = 200; 5537 con->file_finished = 1; 5538 return HANDLER_FINISHED; 5539 } 5540 5541 case HTTP_METHOD_UPLOADTOPICASA:{ 5542 Cdbg(DBE, "do HTTP_METHOD_UPLOADTOPICASA"); 5543 5544#if EMBEDDED_EANBLE 5545 if(!con->srv_socket->is_ssl){ 5546 con->http_status = 403; 5547 return HANDLER_FINISHED; 5548 } 5549#endif 5550 5551 buffer* filename = NULL; 5552 buffer* title = NULL; 5553 buffer* auth_token = NULL; 5554 buffer* user_id = NULL; 5555 buffer* album_id = NULL; 5556 long response_result = 0; 5557 5558 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "FILENAME"))) { 5559 filename = ds->value; 5560 buffer_urldecode_path(filename); 5561 } else { 5562 con->http_status = 400; 5563 return HANDLER_FINISHED; 5564 } 5565 5566 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TITLE"))) { 5567 title = ds->value; 5568 buffer_urldecode_path(title); 5569 } else { 5570 con->http_status = 400; 5571 return HANDLER_FINISHED; 5572 } 5573 5574 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "UID"))) { 5575 user_id = ds->value; 5576 } else { 5577 con->http_status = 400; 5578 return HANDLER_FINISHED; 5579 } 5580 5581 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "AID"))) { 5582 album_id = ds->value; 5583 } else { 5584 con->http_status = 400; 5585 return HANDLER_FINISHED; 5586 } 5587 5588 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TOKEN"))) { 5589 auth_token = ds->value; 5590 } else { 5591 con->http_status = 400; 5592 return HANDLER_FINISHED; 5593 } 5594 5595 CURL *curl; 5596 CURLcode rt; 5597 5598 #if 0 5599 _buffer_t upload_response; 5600 #endif 5601 5602 buffer* buffer_photoid; 5603 5604 curl = curl_easy_init(); 5605 if(curl) { 5606 Cdbg(DBE, "curl_easy_init OK"); 5607 5608 char request_url[1024] = "\0"; 5609 sprintf(request_url, "https://picasaweb.google.com/data/feed/api/user/%s/albumid/%s", user_id->ptr, album_id->ptr); 5610 curl_easy_setopt(curl, CURLOPT_URL, request_url); 5611 5612 char photo_path[1024] = "\0"; 5613 sprintf(photo_path, "%s/%s", con->physical.path->ptr, filename->ptr); 5614 5615 FILE *fd; 5616 fd = fopen(photo_path, "rb"); /* open file to upload */ 5617 if(!fd) { 5618 curl_easy_cleanup(curl); 5619 con->http_status = 404; 5620 return HANDLER_FINISHED; 5621 } 5622 5623 /* to get the file size */ 5624 struct stat file_info; 5625 if(fstat(fileno(fd), &file_info) != 0) { 5626 fclose(fd); 5627 curl_easy_cleanup(curl); 5628 con->http_status = 404; 5629 return HANDLER_FINISHED; 5630 } 5631 5632 long file_size = file_info.st_size; 5633 char* file_data = (char*) malloc (sizeof(char)*file_size); 5634 if(file_data == NULL) { 5635 fclose(fd); 5636 curl_easy_cleanup(curl); 5637 con->http_status = 400; 5638 return HANDLER_FINISHED; 5639 } 5640 5641 // copy the file into the buffer: 5642 size_t result = fread( file_data, 1, file_size, fd ); 5643 5644 if (result != file_size) { 5645 free(file_data); 5646 fclose(fd); 5647 curl_easy_cleanup(curl); 5648 con->http_status = 400; 5649 return HANDLER_FINISHED; 5650 } 5651 5652 char mpart1[4096] = "\0"; 5653 sprintf(mpart1, "\nMedia multipart posting\n" 5654 "--END_OF_PART\n" 5655 "Content-Type: application/atom+xml\n\n" 5656 "<entry xmlns='http://www.w3.org/2005/Atom'>\n" 5657 "<title>%s</title>\n" 5658 "<summary></summary>\n" 5659 "<category scheme=\"http://schemas.google.com/g/2005#kind\"\n" 5660 " term=\"http://schemas.google.com/photos/2007#photo\"/>" 5661 "</entry>\n" 5662 "--END_OF_PART\n" 5663 "Content-Type: image/jpeg\n\n", title->ptr); 5664 5665 int mpart1size = strlen(mpart1); 5666 int postdata_length = mpart1size + file_size + strlen("\n--END_OF_PART--"); 5667 char *postdata = (char*)malloc(sizeof(char)*postdata_length); 5668 5669 if(postdata == NULL) { 5670 free(file_data); 5671 fclose(fd); 5672 curl_easy_cleanup(curl); 5673 con->http_status = 400; 5674 return HANDLER_FINISHED; 5675 } 5676 5677 memcpy( postdata, mpart1, mpart1size); 5678 memcpy( postdata + mpart1size, file_data, file_size); 5679 memcpy( postdata + mpart1size + file_size, "\n--END_OF_PART--", strlen("\n--END_OF_PART--") ); 5680 5681 free(file_data); 5682 fclose(fd); 5683 5684 struct curl_slist *headers = NULL; 5685 headers = curl_slist_append(headers,"Content-Type: multipart/related; boundary=\"END_OF_PART\""); 5686 headers = curl_slist_append(headers,"MIME-version: 1.0"); 5687 headers = curl_slist_append(headers,"Expect:"); 5688 headers = curl_slist_append(headers,"GData-Version: 2"); 5689 5690 char authHeader[1024] = "\0"; 5691 sprintf(authHeader, "Authorization: OAuth %s", auth_token->ptr); 5692 headers = curl_slist_append(headers, authHeader); 5693 5694 char content_length[1024] = "\0"; 5695 sprintf(content_length, "Content-Length=%d", file_size); 5696 headers = curl_slist_append(headers, content_length); 5697 5698 curl_easy_setopt(curl, CURLOPT_VERBOSE, 2); 5699 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 5700 curl_easy_setopt(curl, CURLOPT_UPLOAD, 0); 5701 curl_easy_setopt(curl, CURLOPT_POST, 1); 5702 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); 5703 5704 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata); 5705 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postdata_length); 5706 5707 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); 5708 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); 5709 5710 #if 0 5711 memset(&upload_response,0,sizeof(_buffer_t)); 5712 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _picasa_api_buffer_write_func); 5713 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &upload_response); 5714 #endif 5715 5716 Cdbg(DBE, "Uploading..."); 5717 rt = curl_easy_perform(curl); 5718 5719 curl_slist_free_all(headers); 5720 5721 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_result); 5722 5723 #if 0 5724 if( response_result == 201 ){ 5725 Cdbg(DBE, "complete upload...%s", upload_response.data); 5726 5727 xmlDocPtr xml = xmlParseDoc((xmlChar *)upload_response.data); 5728 if(xml){ 5729 xmlNode *rootnode = xmlDocGetRootElement(xml); 5730 Cdbg(1, "rootnode->name=%s", rootnode->name); 5731 if (0 == xmlStrcmp(rootnode->name, BAD_CAST "entry")) { 5732 5733 xmlNodePtr entryChilds = rootnode->xmlChildrenNode; 5734 5735 if( entryChilds != NULL ){ 5736 do{ 5737 if ((!xmlStrcmp(entryChilds->name, BAD_CAST "id")) ){ 5738 // Get the photo id used in uri for update 5739 xmlChar *id= xmlNodeListGetString(xml, entryChilds->xmlChildrenNode, 1); 5740 if( xmlStrncmp(id, BAD_CAST "http://", 7) ){ 5741 buffer_photoid = buffer_init(); 5742 buffer_copy_string( buffer_photoid, id ); 5743 Cdbg(DBE, "buffer_photoid=%s", buffer_photoid->ptr); 5744 } 5745 xmlFree(id); 5746 5747 break; 5748 } 5749 }while( (entryChilds = entryChilds->next)!=NULL ); 5750 } 5751 } 5752 5753 xmlFreeDoc(xml); 5754 } 5755 } 5756 #endif 5757 5758 /* Done. Cleanup. */ 5759 free(postdata); 5760 5761 #if 0 5762 free(upload_response.data); 5763 #endif 5764 5765 curl_easy_cleanup(curl); 5766 } 5767 5768 con->http_status = ( response_result == 201 ) ? 200 : 501; 5769 con->file_finished = 1; 5770 return HANDLER_FINISHED; 5771 } 5772 5773 case HTTP_METHOD_UPLOADTOFLICKR:{ 5774 Cdbg(1, "do HTTP_METHOD_UPLOADTOFLICKR"); 5775 5776#if EMBEDDED_EANBLE 5777 if(!con->srv_socket->is_ssl){ 5778 con->http_status = 403; 5779 return HANDLER_FINISHED; 5780 } 5781#endif 5782 5783 buffer* filename = NULL; 5784 buffer* title = NULL; 5785 buffer* auth_token = NULL; 5786 5787 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "FILENAME"))) { 5788 filename = ds->value; 5789 buffer_urldecode_path(filename); 5790 } else { 5791 con->http_status = 400; 5792 return HANDLER_FINISHED; 5793 } 5794 5795 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TITLE"))) { 5796 title = ds->value; 5797 buffer_urldecode_path(title); 5798 } else { 5799 con->http_status = 400; 5800 return HANDLER_FINISHED; 5801 } 5802 5803 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TOKEN"))) { 5804 auth_token = ds->value; 5805 } else { 5806 con->http_status = 400; 5807 return HANDLER_FINISHED; 5808 } 5809#if 0 5810 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "PHOTOSET"))) { 5811 photoset = ds->value; 5812 } else { 5813 con->http_status = 400; 5814 return HANDLER_FINISHED; 5815 } 5816#endif 5817 //char api_key[100] = "37140360286c5cd9952023fa8b662a64"; 5818 //char secret[100] = "804b51d14d840d6e"; 5819 char api_key[100] = "c0466d7736e0275d062ce64aefaacfe0"; 5820 char secret[100] = "228e160cf8805246"; 5821 5822 CURL *curl; 5823 CURLcode rt; 5824 struct curl_httppost *formpost = NULL; 5825 struct curl_httppost *lastptr = NULL; 5826 char md5[129]; 5827 char* response_str; 5828 buffer* buffer_photoid = buffer_init(); 5829 5830 curl = curl_easy_init(); 5831 if(curl) { 5832 Cdbg(1, "curl_easy_init OK"); 5833 5834 /* Set Host to target in HTTP header, and set response handler 5835 * function */ 5836 curl_easy_setopt(curl, CURLOPT_URL, "https://api.flickr.com/services/upload/"); 5837 /* curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); */ 5838 5839 /* 5840 char input_string[1024] = "\0"; 5841 sprintf(input_string, "api_key%sauth_token%sdescription%stags%stitle%s", api_key, auth_token->ptr, description, tags, title); 5842 Cdbg(1, "input_string=%s", input_string); 5843 md5String(secret, input_string, md5); 5844 */ 5845 5846 md5sum(md5, 7, secret, "api_key", api_key, "auth_token", auth_token->ptr, "title", title->ptr); 5847 Cdbg(1, "md5=%s", md5); 5848 5849 /* Build the form post */ 5850 curl_formadd(&formpost, &lastptr, 5851 CURLFORM_COPYNAME, "api_key", 5852 CURLFORM_COPYCONTENTS, api_key, CURLFORM_END); 5853 5854 curl_formadd(&formpost, &lastptr, 5855 CURLFORM_COPYNAME, "auth_token", 5856 CURLFORM_COPYCONTENTS, auth_token->ptr, CURLFORM_END); 5857 5858 curl_formadd(&formpost, &lastptr, 5859 CURLFORM_COPYNAME, "api_sig", 5860 CURLFORM_COPYCONTENTS, md5, CURLFORM_END); 5861 5862 curl_formadd(&formpost, &lastptr, 5863 CURLFORM_COPYNAME, "title", 5864 CURLFORM_COPYCONTENTS, title->ptr, CURLFORM_END); 5865 5866 char photo_path[1024] = "\0"; 5867 sprintf(photo_path, "%s/%s", con->physical.path->ptr, filename->ptr); 5868 Cdbg(1, "photo_path=%s", photo_path); 5869 5870 //- check file exists 5871 if(!file_exist(photo_path)){ 5872 curl_easy_cleanup(curl); 5873 curl_formfree(formpost); 5874 buffer_free(buffer_photoid); 5875 con->http_status = 404; 5876 return HANDLER_FINISHED; 5877 } 5878 5879 curl_formadd(&formpost, &lastptr, 5880 CURLFORM_COPYNAME, "photo", 5881 CURLFORM_FILE, photo_path, CURLFORM_END); 5882 5883 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); 5884 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); 5885 5886 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); 5887 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_callback_func); 5888 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_str); 5889 5890 Cdbg(1, "Uploading..."); 5891 rt = curl_easy_perform(curl); 5892 5893 #if 0 5894 /* now extract transfer info */ 5895 double speed_upload, total_time; 5896 curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed_upload); 5897 curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time); 5898 5899 Cdbg(1, "Speed: %.3f bytes/sec during %.3f seconds, response_str=%s", 5900 speed_upload, total_time, response_str); 5901 #endif 5902 5903 xmlDocPtr xml = xmlParseMemory(response_str, strlen(response_str)); 5904 if(xml){ 5905 xmlNode *rootnode = xmlDocGetRootElement(xml); 5906 5907 if (0 == xmlStrcmp(rootnode->name, BAD_CAST "rsp")) { 5908 5909 xmlChar *stat = xmlGetProp(rootnode,(const xmlChar*) "stat"); 5910 5911 if (0 == xmlStrcmp(stat, BAD_CAST "ok")) { 5912 5913 xmlNode *childnode; 5914 for (childnode = rootnode->children; childnode; childnode = childnode->next) { 5915 if (0 == xmlStrcmp(childnode->name, BAD_CAST "photoid")) { 5916 xmlChar *photoid = xmlNodeGetContent(childnode); 5917 buffer_copy_string( buffer_photoid, photoid ); 5918 break; 5919 } 5920 } 5921 } 5922 } 5923 5924 xmlFreeDoc(xml); 5925 } 5926 5927 free(response_str); 5928 5929 /* Done. Cleanup. */ 5930 curl_easy_cleanup(curl); 5931 curl_formfree(formpost); 5932 } 5933 5934 if(!buffer_is_empty(buffer_photoid)){ 5935 5936 Cdbg(1, "buffer_photoid=%s", buffer_photoid->ptr); 5937#if 0 5938 5939 //- set photo to photoset 5940 //if(!buffer_is_empty(photoset)){ 5941 if(buffer_is_empty(photoset)){ 5942 5943 char* response_str2; 5944 struct curl_httppost *formpost2 = NULL; 5945 struct curl_httppost *lastptr2 = NULL; 5946 curl = curl_easy_init(); 5947 if(curl) { 5948 curl_easy_setopt(curl, CURLOPT_URL, "http://api.flickr.com/services/rest/"); 5949 5950 md5sum(md5, 11, secret, "method", "flickr.photosets.addPhoto", "api_key", api_key, "auth_token", auth_token->ptr, "photoset_id", photoset->ptr, "photo_id", buffer_photoid->ptr); 5951 Cdbg(1, "md5=%s, photoset=%s", md5, photoset->ptr); 5952 5953 /* Build the form post */ 5954 curl_formadd(&formpost2, &lastptr2, 5955 CURLFORM_COPYNAME, "method", 5956 CURLFORM_COPYCONTENTS, "flickr.photosets.addPhoto", CURLFORM_END); 5957 5958 curl_formadd(&formpost2, &lastptr2, 5959 CURLFORM_COPYNAME, "api_key", 5960 CURLFORM_COPYCONTENTS, api_key, CURLFORM_END); 5961 5962 curl_formadd(&formpost2, &lastptr2, 5963 CURLFORM_COPYNAME, "photoset_id", 5964 CURLFORM_COPYCONTENTS, photoset->ptr, CURLFORM_END); 5965 5966 curl_formadd(&formpost2, &lastptr2, 5967 CURLFORM_COPYNAME, "photo_id", 5968 CURLFORM_COPYCONTENTS, buffer_photoid->ptr, CURLFORM_END); 5969 5970 curl_formadd(&formpost2, &lastptr2, 5971 CURLFORM_COPYNAME, "auth_token", 5972 CURLFORM_COPYCONTENTS, auth_token->ptr, CURLFORM_END); 5973 5974 curl_formadd(&formpost2, &lastptr2, 5975 CURLFORM_COPYNAME, "api_sig", 5976 CURLFORM_COPYCONTENTS, md5, CURLFORM_END); 5977 5978 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost2); 5979 5980 #if 1 5981 rt = curl_easy_perform(curl); 5982 5983 if (rt) { 5984 Cdbg(1, "An error occurred during upload! %s", curl_easy_strerror(rt)); 5985 } 5986 #else 5987 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_callback_func); 5988 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_str2); 5989 Cdbg(1, "2", md5); 5990 5991 rt = curl_easy_perform(curl); 5992 5993 Cdbg(1, "2, response_str2=%s", response_str2); 5994 xmlDocPtr xml = xmlParseMemory(response_str2, strlen(response_str2)); 5995 if(xml){ 5996 xmlNode *rootnode = xmlDocGetRootElement(xml); 5997 5998 if (0 == xmlStrcmp(rootnode->name, BAD_CAST "rsp")) { 5999 6000 xmlChar *stat = xmlGetProp(rootnode,(const xmlChar*) "stat"); 6001 6002 if (0 == xmlStrcmp(stat, BAD_CAST "ok")) { 6003 Cdbg(1, "set photoset OK..."); 6004 } 6005 6006 xmlFreeDoc(xml); 6007 } 6008 } 6009 6010 free(response_str2); 6011 #endif 6012 6013 /* Done. Cleanup. */ 6014 curl_easy_cleanup(curl); 6015 curl_formfree(formpost2); 6016 } 6017 6018 } 6019#endif 6020 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); 6021 6022 b = buffer_init(); 6023 6024 buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>")); 6025 buffer_append_string_len(b,CONST_STR_LEN("<result>")); 6026 buffer_append_string_len(b,CONST_STR_LEN("<photoid>")); 6027 buffer_append_string_buffer(b,buffer_photoid); 6028 buffer_append_string_len(b,CONST_STR_LEN("</photoid>")); 6029 buffer_append_string_len(b,CONST_STR_LEN("</result>")); 6030 6031 chunkqueue_append_buffer(con->write_queue, b); 6032 buffer_free(b); 6033 6034 con->http_status = 200; 6035 } 6036 else 6037 con->http_status = 501; 6038 6039 buffer_free(buffer_photoid); 6040 6041 con->file_finished = 1; 6042 return HANDLER_FINISHED; 6043 } 6044 6045 case HTTP_METHOD_UPLOADTOTWITTER:{ 6046 Cdbg(DBE, "do HTTP_METHOD_UPLOADTOTWITTER"); 6047 6048#if EMBEDDED_EANBLE 6049 if(!con->srv_socket->is_ssl){ 6050 con->http_status = 403; 6051 return HANDLER_FINISHED; 6052 } 6053#endif 6054 6055 buffer* filename = NULL; 6056 buffer* title = NULL; 6057 buffer* auth_token = NULL; 6058 buffer* auth_secret = NULL; 6059 buffer* nonce = NULL; 6060 buffer* timestamp = NULL; 6061 buffer* signature = NULL; 6062 buffer* photo_size_limit = NULL; 6063 6064 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "FILENAME"))) { 6065 filename = ds->value; 6066 buffer_urldecode_path(filename); 6067 } else { 6068 con->http_status = 400; 6069 return HANDLER_FINISHED; 6070 } 6071 6072 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TITLE"))) { 6073 title = ds->value; 6074 buffer_urldecode_path(title); 6075 } else { 6076 con->http_status = 400; 6077 return HANDLER_FINISHED; 6078 } 6079 6080 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TOKEN"))) { 6081 auth_token = ds->value; 6082 } else { 6083 con->http_status = 400; 6084 return HANDLER_FINISHED; 6085 } 6086 6087 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "SECRET"))) { 6088 auth_secret = ds->value; 6089 } else { 6090 con->http_status = 400; 6091 return HANDLER_FINISHED; 6092 } 6093 6094 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "NONCE"))) { 6095 nonce = ds->value; 6096 } else { 6097 con->http_status = 400; 6098 return HANDLER_FINISHED; 6099 } 6100 6101 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "TIMESTAMP"))) { 6102 timestamp = ds->value; 6103 } else { 6104 con->http_status = 400; 6105 return HANDLER_FINISHED; 6106 } 6107 6108 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "SIGNATURE"))) { 6109 signature = ds->value; 6110 } else { 6111 con->http_status = 400; 6112 return HANDLER_FINISHED; 6113 } 6114 6115 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "PHOTOSIZELIMIT"))) { 6116 photo_size_limit = ds->value; 6117 } else { 6118 con->http_status = 400; 6119 return HANDLER_FINISHED; 6120 } 6121 6122 char consumer_key[100] = "hBQrdHdHClXylEI6by40DTMVA"; 6123 //char consumer_secret[100] = "2PlfH4Bx9XVZTYjOz3hoeqAY31aPUx916hU0R4gu0D0uCZ4Y4L"; 6124 6125 CURL *curl; 6126 CURLcode rt; 6127 struct curl_httppost *formpost = NULL; 6128 struct curl_httppost *lastptr = NULL; 6129 char* response_str = NULL; 6130 long response_code = 0; 6131 6132 curl = curl_easy_init(); 6133 if(curl) { 6134 Cdbg(DBE, "curl_easy_init OK"); 6135 6136 /* Set Host to target in HTTP header, and set response handler 6137 * function */ 6138 //curl_easy_setopt(curl, CURLOPT_URL, "https://upload.twitter.com/1.1/statuses/update_with_media.json"); 6139 curl_easy_setopt(curl, CURLOPT_URL, "https://api.twitter.com/1.1/statuses/update_with_media.json"); 6140 6141 struct curl_slist *headers = NULL; 6142 char authHeader[1024] = "\0"; 6143 sprintf(authHeader, "Authorization: OAuth" 6144 " oauth_consumer_key=\"%s\"," 6145 " oauth_nonce=\"%s\"," 6146 " oauth_signature_method=\"HMAC-SHA1\"," 6147 " oauth_timestamp=\"%s\"," 6148 " oauth_token=\"%s\"," 6149 " oauth_version=\"1.0\"," 6150 " oauth_signature=\"%s\"", 6151 consumer_key, 6152 nonce->ptr, 6153 timestamp->ptr, 6154 auth_token->ptr, 6155 signature->ptr); 6156 headers = curl_slist_append(headers, authHeader); 6157 6158 headers = curl_slist_append(headers,"Content-Type: multipart/form-data"); 6159 6160 char photo_path[1024] = "\0"; 6161 sprintf(photo_path, "%s/%s", con->physical.path->ptr, filename->ptr); 6162 Cdbg(DBE, "photo_path=%s", photo_path); 6163 6164 FILE *fd; 6165 fd = fopen(photo_path, "rb"); /* open file to upload */ 6166 if(!fd) { 6167 curl_easy_cleanup(curl); 6168 con->http_status = 404; 6169 return HANDLER_FINISHED; 6170 } 6171 6172 /* to get the file size */ 6173 struct stat file_info; 6174 if(fstat(fileno(fd), &file_info) != 0) { 6175 fclose(fd); 6176 curl_easy_cleanup(curl); 6177 con->http_status = 404; 6178 return HANDLER_FINISHED; 6179 } 6180 6181 long file_size = file_info.st_size; 6182 long l_photo_size_limit = atol(photo_size_limit->ptr); 6183 fclose(fd); 6184 6185 if(file_size>=l_photo_size_limit){ 6186 curl_easy_cleanup(curl); 6187 con->http_status = 501; 6188 return HANDLER_FINISHED; 6189 } 6190 6191 curl_formadd(&formpost, &lastptr, 6192 CURLFORM_COPYNAME, "status", 6193 CURLFORM_COPYCONTENTS, title->ptr, CURLFORM_END); 6194 6195 curl_formadd(&formpost, &lastptr, 6196 CURLFORM_COPYNAME, "media[]", 6197 CURLFORM_FILE, photo_path, CURLFORM_END); 6198 6199 curl_easy_setopt(curl, CURLOPT_VERBOSE, 2); 6200 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 6201 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); 6202 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); 6203 6204 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); 6205 6206 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_callback_func); 6207 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_str); 6208 6209 Cdbg(DBE, "Uploading..."); 6210 rt = curl_easy_perform(curl); 6211 6212 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); 6213 6214 Cdbg(DBE, "response_code=%d, response_str = %s", response_code, response_str); 6215 6216 free(response_str); 6217 6218 /* Done. Cleanup. */ 6219 curl_easy_cleanup(curl); 6220 curl_formfree(formpost); 6221 } 6222 6223 6224 if(response_code==200){ 6225 con->http_status = 200; 6226 } 6227 else 6228 con->http_status = 501; 6229 6230 con->file_finished = 1; 6231 return HANDLER_FINISHED; 6232 } 6233 6234 default: 6235 break; 6236 } 6237 6238 /* not found */ 6239 return HANDLER_GO_ON; 6240} 6241 6242 6243/* this function is called at dlopen() time and inits the callbacks */ 6244#ifndef APP_IPKG 6245int mod_webdav_plugin_init(plugin *p); 6246int mod_webdav_plugin_init(plugin *p) { 6247 p->version = LIGHTTPD_VERSION_ID; 6248 p->name = buffer_init_string("webdav"); 6249 6250 p->init = mod_webdav_init; 6251 p->handle_uri_clean = mod_webdav_uri_handler; 6252 p->handle_physical = mod_webdav_subrequest_handler; 6253 p->set_defaults = mod_webdav_set_defaults; 6254 p->cleanup = mod_webdav_free; 6255 6256 p->data = NULL; 6257 6258 return 0; 6259} 6260#else 6261int aicloud_mod_webdav_plugin_init(plugin *p); 6262int aicloud_mod_webdav_plugin_init(plugin *p) { 6263 p->version = LIGHTTPD_VERSION_ID; 6264 p->name = buffer_init_string("webdav"); 6265 6266 p->init = mod_webdav_init; 6267 p->handle_uri_clean = mod_webdav_uri_handler; 6268 p->handle_physical = mod_webdav_subrequest_handler; 6269 p->set_defaults = mod_webdav_set_defaults; 6270 p->cleanup = mod_webdav_free; 6271 6272 p->data = NULL; 6273 6274 return 0; 6275} 6276#endif 6277