Changeset 22962
- Timestamp:
- 2010-09-06T22:49:31+02:00 (7 years ago)
- Location:
- branches/backfire/package/uhttpd
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/backfire/package/uhttpd/Makefile
r22608 r22962 9 9 10 10 PKG_NAME:=uhttpd 11 PKG_RELEASE:=1 411 PKG_RELEASE:=17 12 12 13 13 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) -
branches/backfire/package/uhttpd/files/uhttpd.config
r22590 r22962 27 27 # Default is /cgi-bin 28 28 option cgi_prefix /cgi-bin 29 30 # List of extension->interpreter mappings. 31 # Files with an associated interpreter can 32 # be called outside of the CGI prefix and do 33 # not need to be executable. 34 # list interpreter ".php=/usr/bin/php-cgi" 35 # list interpreter ".cgi=/usr/bin/perl" 29 36 30 37 # Lua url prefix and handler script. -
branches/backfire/package/uhttpd/files/uhttpd.init
r22594 r22962 57 57 local cfg="$1" 58 58 local realm="$(uci_get system.@system[0].hostname)" 59 local listen http https 59 local listen http https interpreter path 60 60 61 61 append_arg "$cfg" home "-h" … … 77 77 for listen in $http; do 78 78 append UHTTPD_ARGS "-p $listen" 79 done 80 81 config_get interpreter "$cfg" interpreter 82 for path in $interpreter; do 83 append UHTTPD_ARGS "-i $path" 79 84 done 80 85 -
branches/backfire/package/uhttpd/src/uhttpd-cgi.c
r22590 r22962 136 136 137 137 138 void uh_cgi_request(struct client *cl, struct http_request *req, struct path_info *pi) 139 { 140 int i, hdroff, bufoff; 138 void uh_cgi_request( 139 struct client *cl, struct http_request *req, 140 struct path_info *pi, struct interpreter *ip 141 ) { 142 int i, hdroff, bufoff, rv; 141 143 int hdrlen = 0; 142 144 int buflen = 0; … … 200 202 dup2(wfd[0], 0); 201 203 202 /* check for regular, world-executable file */203 if( ( pi->stat.st_mode & S_IFREG) &&204 (pi->stat.st_mode & S_IXOTH)204 /* check for regular, world-executable file _or_ interpreter */ 205 if( ((pi->stat.st_mode & S_IFREG) && 206 (pi->stat.st_mode & S_IXOTH)) || (ip != NULL) 205 207 ) { 206 208 /* build environment */ … … 321 323 perror("chdir()"); 322 324 323 execl(pi->phys, pi->phys, NULL); 325 if( ip != NULL ) 326 execl(ip->path, ip->path, pi->phys, NULL); 327 else 328 execl(pi->phys, pi->phys, NULL); 324 329 325 330 /* in case it fails ... */ … … 328 333 "Unable to launch the requested CGI program:\n" 329 334 " %s: %s\n", 330 pi->phys, strerror(errno)335 ip ? ip->path : pi->phys, strerror(errno) 331 336 ); 332 337 } … … 372 377 memset(hdr, 0, sizeof(hdr)); 373 378 374 timeout.tv_sec = cl->server->conf->script_timeout;375 timeout.tv_usec = 0;376 377 #define ensure(x) \378 do { if( x < 0 ) goto out; } while(0)379 380 379 /* I/O loop, watch our pipe ends and dispatch child reads/writes from/to socket */ 381 380 while( 1 ) … … 387 386 FD_SET(wfd[1], &writer); 388 387 388 timeout.tv_sec = (header_sent < 1) ? cl->server->conf->script_timeout : 3; 389 timeout.tv_usec = 0; 390 391 ensure_out(rv = select_intr(fd_max, &reader, 392 (content_length > -1) ? &writer : NULL, NULL, &timeout)); 393 394 /* timeout */ 395 if( rv == 0 ) 396 { 397 ensure_out(kill(child, 0)); 398 } 399 389 400 /* wait until we can read or write or both */ 390 if( select_intr(fd_max, &reader, 391 (content_length > -1) ? &writer : NULL, NULL, 392 (header_sent < 1) ? &timeout : NULL) > 0 393 ) { 401 else if( rv > 0 ) 402 { 394 403 /* ready to write to cgi program */ 395 404 if( FD_ISSET(wfd[1], &writer) ) … … 399 408 { 400 409 /* read it from socket ... */ 401 if( (buflen = uh_tcp_recv(cl, buf, min(content_length, sizeof(buf)))) > 0 ) 410 ensure_out(buflen = uh_tcp_recv(cl, buf, 411 min(content_length, sizeof(buf)))); 412 413 if( buflen > 0 ) 402 414 { 403 415 /* ... and write it to child's stdin */ … … 452 464 { 453 465 /* write status */ 454 ensure (uh_http_sendf(cl, NULL,466 ensure_out(uh_http_sendf(cl, NULL, 455 467 "HTTP/%.1f %03d %s\r\n" 456 468 "Connection: close\r\n", … … 462 474 !uh_cgi_header_lookup(res, "Content-Type") 463 475 ) { 464 ensure (uh_http_send(cl, NULL,476 ensure_out(uh_http_send(cl, NULL, 465 477 "Content-Type: text/plain\r\n", -1)); 466 478 } … … 470 482 !uh_cgi_header_lookup(res, "Transfer-Encoding") 471 483 ) { 472 ensure (uh_http_send(cl, NULL,484 ensure_out(uh_http_send(cl, NULL, 473 485 "Transfer-Encoding: chunked\r\n", -1)); 474 486 } … … 477 489 foreach_header(i, res->headers) 478 490 { 479 ensure (uh_http_sendf(cl, NULL, "%s: %s\r\n",491 ensure_out(uh_http_sendf(cl, NULL, "%s: %s\r\n", 480 492 res->headers[i], res->headers[i+1])); 481 493 } 482 494 483 495 /* terminate header */ 484 ensure (uh_http_send(cl, NULL, "\r\n", -1));496 ensure_out(uh_http_send(cl, NULL, "\r\n", -1)); 485 497 486 498 /* push out remaining head buffer */ 487 499 if( hdroff < hdrlen ) 488 ensure (uh_http_send(cl, req, &hdr[hdroff], hdrlen - hdroff));500 ensure_out(uh_http_send(cl, req, &hdr[hdroff], hdrlen - hdroff)); 489 501 } 490 502 … … 492 504 else if( hdrlen >= sizeof(hdr) ) 493 505 { 494 ensure (uh_cgi_error_500(cl, req,506 ensure_out(uh_cgi_error_500(cl, req, 495 507 "The CGI program generated an invalid response:\n\n")); 496 508 497 ensure (uh_http_send(cl, req, hdr, hdrlen));509 ensure_out(uh_http_send(cl, req, hdr, hdrlen)); 498 510 } 499 511 … … 506 518 /* push out remaining read buffer */ 507 519 if( bufoff < buflen ) 508 ensure (uh_http_send(cl, req, &buf[bufoff], buflen - bufoff));520 ensure_out(uh_http_send(cl, req, &buf[bufoff], buflen - bufoff)); 509 521 510 522 header_sent = 1; … … 514 526 515 527 /* headers complete, pass through buffer to socket */ 516 ensure (uh_http_send(cl, req, buf, buflen));528 ensure_out(uh_http_send(cl, req, buf, buflen)); 517 529 } 518 530 … … 534 546 */ 535 547 536 ensure (uh_http_sendf(cl, NULL,548 ensure_out(uh_http_sendf(cl, NULL, 537 549 "HTTP/%.1f 200 OK\r\n" 538 550 "Content-Type: text/plain\r\n" … … 542 554 )); 543 555 544 ensure (uh_http_send(cl, req, hdr, hdrlen));556 ensure_out(uh_http_send(cl, req, hdr, hdrlen)); 545 557 } 546 558 547 559 /* send final chunk if we're in chunked transfer mode */ 548 ensure (uh_http_send(cl, req, "", 0));560 ensure_out(uh_http_send(cl, req, "", 0)); 549 561 break; 550 562 } … … 557 569 if( (errno != EINTR) && ! header_sent ) 558 570 { 559 ensure (uh_http_sendhf(cl, 504, "Gateway Timeout",571 ensure_out(uh_http_sendhf(cl, 504, "Gateway Timeout", 560 572 "The CGI script took too long to produce " 561 573 "a response")); … … 563 575 564 576 /* send final chunk if we're in chunked transfer mode */ 565 ensure (uh_http_send(cl, req, "", 0));577 ensure_out(uh_http_send(cl, req, "", 0)); 566 578 567 579 break; -
branches/backfire/package/uhttpd/src/uhttpd-cgi.h
r20428 r22962 26 26 27 27 void uh_cgi_request( 28 struct client *cl, struct http_request *req, struct path_info *pi 28 struct client *cl, struct http_request *req, 29 struct path_info *pi, struct interpreter *ip 29 30 ); 30 31 -
branches/backfire/package/uhttpd/src/uhttpd-file.c
r22608 r22962 98 98 } 99 99 100 #define ensure_ret(x) \ 101 do { if( x < 0 ) return; } while(0) 102 103 static void uh_file_response_ok_hdrs(struct client *cl, struct http_request *req, struct stat *s) 100 101 static int uh_file_response_ok_hdrs(struct client *cl, struct http_request *req, struct stat *s) 104 102 { 105 103 ensure_ret(uh_http_sendf(cl, NULL, "Connection: close\r\n")); … … 111 109 } 112 110 113 ensure_ret(uh_http_sendf(cl, NULL, "Date: %s\r\n", uh_file_unix2date(time(NULL))));114 } 115 116 static voiduh_file_response_200(struct client *cl, struct http_request *req, struct stat *s)111 return uh_http_sendf(cl, NULL, "Date: %s\r\n", uh_file_unix2date(time(NULL))); 112 } 113 114 static int uh_file_response_200(struct client *cl, struct http_request *req, struct stat *s) 117 115 { 118 116 ensure_ret(uh_http_sendf(cl, NULL, "HTTP/%.1f 200 OK\r\n", req->version)); 119 uh_file_response_ok_hdrs(cl, req, s);120 } 121 122 static voiduh_file_response_304(struct client *cl, struct http_request *req, struct stat *s)117 return uh_file_response_ok_hdrs(cl, req, s); 118 } 119 120 static int uh_file_response_304(struct client *cl, struct http_request *req, struct stat *s) 123 121 { 124 122 ensure_ret(uh_http_sendf(cl, NULL, "HTTP/%.1f 304 Not Modified\r\n", req->version)); 125 uh_file_response_ok_hdrs(cl, req, s);126 } 127 128 static voiduh_file_response_412(struct client *cl, struct http_request *req)129 { 130 ensure_ret(uh_http_sendf(cl, NULL,123 return uh_file_response_ok_hdrs(cl, req, s); 124 } 125 126 static int uh_file_response_412(struct client *cl, struct http_request *req) 127 { 128 return uh_http_sendf(cl, NULL, 131 129 "HTTP/%.1f 412 Precondition Failed\r\n" 132 "Connection: close\r\n", req->version) );133 } 134 135 static int uh_file_if_match(struct client *cl, struct http_request *req, struct stat *s )130 "Connection: close\r\n", req->version); 131 } 132 133 static int uh_file_if_match(struct client *cl, struct http_request *req, struct stat *s, int *ok) 136 134 { 137 135 const char *tag = uh_file_mktag(s); … … 153 151 else if( !strcmp(p, "*") || !strcmp(p, tag) ) 154 152 { 155 return 1; 153 *ok = 1; 154 return *ok; 156 155 } 157 156 } 158 157 159 uh_file_response_412(cl, req); 160 return 0; 161 } 162 163 return 1; 164 } 165 166 static int uh_file_if_modified_since(struct client *cl, struct http_request *req, struct stat *s) 158 *ok = 0; 159 ensure_ret(uh_file_response_412(cl, req)); 160 return *ok; 161 } 162 163 *ok = 1; 164 return *ok; 165 } 166 167 static int uh_file_if_modified_since(struct client *cl, struct http_request *req, struct stat *s, int *ok) 167 168 { 168 169 char *hdr = uh_file_header_lookup(req, "If-Modified-Since"); 170 *ok = 1; 169 171 170 172 if( hdr ) 171 173 { 172 if( uh_file_date2unix(hdr) < s->st_mtime ) 173 { 174 return 1; 175 } 176 else 177 { 178 uh_file_response_304(cl, req, s); 179 return 0; 180 } 181 } 182 183 return 1; 184 } 185 186 static int uh_file_if_none_match(struct client *cl, struct http_request *req, struct stat *s) 174 if( uh_file_date2unix(hdr) >= s->st_mtime ) 175 { 176 *ok = 0; 177 ensure_ret(uh_file_response_304(cl, req, s)); 178 } 179 } 180 181 return *ok; 182 } 183 184 static int uh_file_if_none_match(struct client *cl, struct http_request *req, struct stat *s, int *ok) 187 185 { 188 186 const char *tag = uh_file_mktag(s); … … 190 188 char *p; 191 189 int i; 190 *ok = 1; 192 191 193 192 if( hdr ) … … 204 203 else if( !strcmp(p, "*") || !strcmp(p, tag) ) 205 204 { 205 *ok = 0; 206 206 207 if( (req->method == UH_HTTP_MSG_GET) || 207 208 (req->method == UH_HTTP_MSG_HEAD) ) 208 uh_file_response_304(cl, req, s);209 ensure_ret(uh_file_response_304(cl, req, s)); 209 210 else 210 uh_file_response_412(cl, req);211 212 return 0;211 ensure_ret(uh_file_response_412(cl, req)); 212 213 break; 213 214 } 214 215 } 215 216 } 216 217 217 return 1;218 } 219 220 static int uh_file_if_range(struct client *cl, struct http_request *req, struct stat *s )218 return *ok; 219 } 220 221 static int uh_file_if_range(struct client *cl, struct http_request *req, struct stat *s, int *ok) 221 222 { 222 223 char *hdr = uh_file_header_lookup(req, "If-Range"); 224 *ok = 1; 223 225 224 226 if( hdr ) 225 227 { 226 uh_file_response_412(cl, req);227 return 0;228 } 229 230 return 1;231 } 232 233 static int uh_file_if_unmodified_since(struct client *cl, struct http_request *req, struct stat *s )228 *ok = 0; 229 ensure_ret(uh_file_response_412(cl, req)); 230 } 231 232 return *ok; 233 } 234 235 static int uh_file_if_unmodified_since(struct client *cl, struct http_request *req, struct stat *s, int *ok) 234 236 { 235 237 char *hdr = uh_file_header_lookup(req, "If-Unmodified-Since"); 238 *ok = 1; 236 239 237 240 if( hdr ) … … 239 242 if( uh_file_date2unix(hdr) <= s->st_mtime ) 240 243 { 241 uh_file_response_412(cl, req); 242 return 0; 243 } 244 } 245 246 return 1; 247 } 248 249 250 #define ensure_out(x) \ 251 do { if( x < 0 ) goto out; } while(0) 244 *ok = 0; 245 ensure_ret(uh_file_response_412(cl, req)); 246 } 247 } 248 249 return *ok; 250 } 251 252 252 253 253 static int uh_file_scandir_filter_dir(const struct dirent *e) … … 336 336 { 337 337 int rlen; 338 int ok = 1; 338 339 int fd = -1; 339 340 char buf[UH_LIMIT_MSGHEAD]; … … 343 344 { 344 345 /* test preconditions */ 345 if( 346 uh_file_if_modified_since(cl, req, &pi->stat) && 347 uh_file_if_match(cl, req, &pi->stat) && 348 uh_file_if_range(cl, req, &pi->stat) && 349 uh_file_if_unmodified_since(cl, req, &pi->stat) && 350 uh_file_if_none_match(cl, req, &pi->stat) 351 ) { 346 if(ok) ensure_out(uh_file_if_modified_since(cl, req, &pi->stat, &ok)); 347 if(ok) ensure_out(uh_file_if_match(cl, req, &pi->stat, &ok)); 348 if(ok) ensure_out(uh_file_if_range(cl, req, &pi->stat, &ok)); 349 if(ok) ensure_out(uh_file_if_unmodified_since(cl, req, &pi->stat, &ok)); 350 if(ok) ensure_out(uh_file_if_none_match(cl, req, &pi->stat, &ok)); 351 352 if( ok > 0 ) 353 { 352 354 /* write status */ 353 uh_file_response_200(cl, req, &pi->stat);355 ensure_out(uh_file_response_200(cl, req, &pi->stat)); 354 356 355 357 ensure_out(uh_http_sendf(cl, NULL, "Content-Type: %s\r\n", uh_file_mime_lookup(pi->name))); … … 386 388 { 387 389 /* write status */ 388 uh_file_response_200(cl, req, NULL);390 ensure_out(uh_file_response_200(cl, req, NULL)); 389 391 390 392 if( req->version > 1.0 ) -
branches/backfire/package/uhttpd/src/uhttpd-tls.c
r21763 r22962 71 71 int uh_tls_client_recv(struct client *c, void *buf, int len) 72 72 { 73 return SSL_read(c->tls, buf, len); 73 int rv = SSL_read(c->tls, buf, len); 74 return (rv > 0) ? rv : -1; 74 75 } 75 76 76 77 int uh_tls_client_send(struct client *c, void *buf, int len) 77 78 { 78 return SSL_write(c->tls, buf, len); 79 int rv = SSL_write(c->tls, buf, len); 80 return (rv > 0) ? rv : -1; 79 81 } 80 82 -
branches/backfire/package/uhttpd/src/uhttpd-utils.c
r22590 r22962 113 113 sigemptyset(&ssn); 114 114 sigaddset(&ssn, SIGCHLD); 115 sigaddset(&ssn, SIGPIPE); 115 116 sigprocmask(SIG_UNBLOCK, &ssn, &sso); 116 117 … … 194 195 } 195 196 196 #define ensure(x) \197 do { if( x < 0 ) return -1; } while(0)198 197 199 198 int uh_http_sendhf(struct client *cl, int code, const char *summary, const char *fmt, ...) … … 212 211 ); 213 212 214 ensure (uh_tcp_send(cl, buffer, len));213 ensure_ret(uh_tcp_send(cl, buffer, len)); 215 214 216 215 va_start(ap, fmt); … … 218 217 va_end(ap); 219 218 220 ensure (uh_http_sendc(cl, buffer, len));221 ensure (uh_http_sendc(cl, NULL, 0));219 ensure_ret(uh_http_sendc(cl, buffer, len)); 220 ensure_ret(uh_http_sendc(cl, NULL, 0)); 222 221 223 222 return 0; … … 236 235 { 237 236 clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len); 238 ensure (uh_tcp_send(cl, chunk, clen));239 ensure (uh_tcp_send(cl, data, len));240 ensure (uh_tcp_send(cl, "\r\n", 2));237 ensure_ret(uh_tcp_send(cl, chunk, clen)); 238 ensure_ret(uh_tcp_send(cl, data, len)); 239 ensure_ret(uh_tcp_send(cl, "\r\n", 2)); 241 240 } 242 241 else 243 242 { 244 ensure (uh_tcp_send(cl, "0\r\n\r\n", 5));243 ensure_ret(uh_tcp_send(cl, "0\r\n\r\n", 5)); 245 244 } 246 245 … … 260 259 261 260 if( (req != NULL) && (req->version > 1.0) ) 262 ensure (uh_http_sendc(cl, buffer, len));261 ensure_ret(uh_http_sendc(cl, buffer, len)); 263 262 else if( len > 0 ) 264 ensure (uh_tcp_send(cl, buffer, len));263 ensure_ret(uh_tcp_send(cl, buffer, len)); 265 264 266 265 return 0; … … 274 273 275 274 if( (req != NULL) && (req->version > 1.0) ) 276 ensure (uh_http_sendc(cl, buf, len));275 ensure_ret(uh_http_sendc(cl, buf, len)); 277 276 else if( len > 0 ) 278 ensure (uh_tcp_send(cl, buf, len));277 ensure_ret(uh_tcp_send(cl, buf, len)); 279 278 280 279 return 0; … … 606 605 607 606 608 static char uh_realms[UH_LIMIT_AUTHREALMS * sizeof(struct auth_realm)] = { 0 }; 609 static int uh_realm_count = 0; 607 static struct auth_realm *uh_realms = NULL; 610 608 611 609 struct auth_realm * uh_auth_add(char *path, char *user, char *pass) … … 615 613 struct spwd *spwd; 616 614 617 if( uh_realm_count < UH_LIMIT_AUTHREALMS ) 618 { 619 new = (struct auth_realm *) 620 &uh_realms[uh_realm_count * sizeof(struct auth_realm)]; 621 615 if((new = (struct auth_realm *)malloc(sizeof(struct auth_realm))) != NULL) 616 { 622 617 memset(new, 0, sizeof(struct auth_realm)); 623 618 … … 644 639 memcpy(new->pass, pwd->pw_passwd, 645 640 min(strlen(pwd->pw_passwd), sizeof(new->pass) - 1)); 646 } 641 } 647 642 } 648 643 … … 656 651 if( new->pass[0] ) 657 652 { 658 uh_realm_count++; 653 new->next = uh_realms; 654 uh_realms = new; 655 659 656 return new; 660 657 } 658 659 free(new); 661 660 } 662 661 … … 678 677 679 678 /* check whether at least one realm covers the requested url */ 680 for( i = 0; i < uh_realm_count; i++ ) 681 { 682 realm = (struct auth_realm *) 683 &uh_realms[i * sizeof(struct auth_realm)]; 684 679 for( realm = uh_realms; realm; realm = realm->next ) 680 { 685 681 rlen = strlen(realm->path); 686 682 … … 722 718 { 723 719 /* find matching realm */ 724 for( i = 0, realm = NULL; i < uh_realm_count; i++ ) 725 { 726 realm = (struct auth_realm *) 727 &uh_realms[i * sizeof(struct auth_realm)]; 728 720 for( realm = uh_realms; realm; realm = realm->next ) 721 { 729 722 rlen = strlen(realm->path); 730 723 … … 736 729 break; 737 730 } 738 739 realm = NULL;740 731 } 741 732 … … 770 761 771 762 772 static char uh_listeners[UH_LIMIT_LISTENERS * sizeof(struct listener)] = { 0 }; 773 static char uh_clients[UH_LIMIT_CLIENTS * sizeof(struct client)] = { 0 }; 774 775 static int uh_listener_count = 0; 776 static int uh_client_count = 0; 777 763 static struct listener *uh_listeners = NULL; 764 static struct client *uh_clients = NULL; 778 765 779 766 struct listener * uh_listener_add(int sock, struct config *conf) … … 782 769 socklen_t sl; 783 770 784 if( uh_listener_count < UH_LIMIT_LISTENERS ) 785 { 786 new = (struct listener *) 787 &uh_listeners[uh_listener_count * sizeof(struct listener)]; 771 if( (new = (struct listener *)malloc(sizeof(struct listener))) != NULL ) 772 { 773 memset(new, 0, sizeof(struct listener)); 788 774 789 775 new->socket = sock; … … 795 781 getsockname(sock, (struct sockaddr *) &(new->addr), &sl); 796 782 797 uh_listener_count++; 798 } 799 800 return new; 783 new->next = uh_listeners; 784 uh_listeners = new; 785 786 return new; 787 } 788 789 return NULL; 801 790 } 802 791 … … 804 793 { 805 794 struct listener *cur = NULL; 806 int i; 807 808 for( i = 0; i < uh_listener_count; i++ ) 809 { 810 cur = (struct listener *) &uh_listeners[i * sizeof(struct listener)]; 811 795 796 for( cur = uh_listeners; cur; cur = cur->next ) 812 797 if( cur->socket == sock ) 813 798 return cur; 814 }815 799 816 800 return NULL; … … 823 807 socklen_t sl; 824 808 825 if( uh_client_count < UH_LIMIT_CLIENTS ) 826 { 827 new = (struct client *) 828 &uh_clients[uh_client_count * sizeof(struct client)]; 809 if( (new = (struct client *)malloc(sizeof(struct client))) != NULL ) 810 { 811 memset(new, 0, sizeof(struct client)); 829 812 830 813 new->socket = sock; … … 841 824 getsockname(sock, (struct sockaddr *) &(new->servaddr), &sl); 842 825 843 uh_client_count++; 826 new->next = uh_clients; 827 uh_clients = new; 844 828 } 845 829 … … 850 834 { 851 835 struct client *cur = NULL; 852 int i; 853 854 for( i = 0; i < uh_client_count; i++ ) 855 { 856 cur = (struct client *) &uh_clients[i * sizeof(struct client)]; 857 836 837 for( cur = uh_clients; cur; cur = cur->next ) 858 838 if( cur->socket == sock ) 859 839 return cur; 860 }861 840 862 841 return NULL; … … 865 844 void uh_client_remove(int sock) 866 845 { 867 struct client *del = uh_client_lookup(sock); 868 869 if( del ) 870 { 871 memmove(del, del + 1, 872 sizeof(uh_clients) - (int)((char *)del - uh_clients) - sizeof(struct client)); 873 874 uh_client_count--; 875 } 876 } 877 878 846 struct client *cur = NULL; 847 struct client *prv = NULL; 848 849 for( cur = uh_clients; cur; prv = cur, cur = cur->next ) 850 { 851 if( cur->socket == sock ) 852 { 853 if( prv ) 854 prv->next = cur->next; 855 else 856 uh_clients = cur->next; 857 858 free(cur); 859 break; 860 } 861 } 862 } 863 864 865 #ifdef HAVE_CGI 866 static struct interpreter *uh_interpreters = NULL; 867 868 struct interpreter * uh_interpreter_add(const char *extn, const char *path) 869 { 870 struct interpreter *new = NULL; 871 872 if( (new = (struct interpreter *) 873 malloc(sizeof(struct interpreter))) != NULL ) 874 { 875 memset(new, 0, sizeof(struct interpreter)); 876 877 memcpy(new->extn, extn, min(strlen(extn), sizeof(new->extn)-1)); 878 memcpy(new->path, path, min(strlen(path), sizeof(new->path)-1)); 879 880 new->next = uh_interpreters; 881 uh_interpreters = new; 882 883 return new; 884 } 885 886 return NULL; 887 } 888 889 struct interpreter * uh_interpreter_lookup(const char *path) 890 { 891 struct interpreter *cur = NULL; 892 const char *e; 893 894 for( cur = uh_interpreters; cur; cur = cur->next ) 895 { 896 e = &path[max(strlen(path) - strlen(cur->extn), 0)]; 897 898 if( !strcmp(e, cur->extn) ) 899 return cur; 900 } 901 902 return NULL; 903 } 904 #endif -
branches/backfire/package/uhttpd/src/uhttpd-utils.h
r22590 r22962 36 36 #define fd_cloexec(fd) \ 37 37 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) 38 39 #define ensure_out(x) \ 40 do { if((x) < 0) goto out; } while(0) 41 42 #define ensure_ret(x) \ 43 do { if((x) < 0) return -1; } while(0) 44 38 45 39 46 struct path_info { … … 102 109 void uh_client_remove(int sock); 103 110 111 #ifdef HAVE_CGI 112 struct interpreter * uh_interpreter_add(const char *extn, const char *path); 113 struct interpreter * uh_interpreter_lookup(const char *path); 104 114 #endif 115 116 #endif -
branches/backfire/package/uhttpd/src/uhttpd.c
r22608 r22962 52 52 FILE *c; 53 53 char line[512]; 54 char * user= NULL;55 char * pass= NULL;54 char *col1 = NULL; 55 char *col2 = NULL; 56 56 char *eol = NULL; 57 57 … … 67 67 if( (line[0] == '/') && (strchr(line, ':') != NULL) ) 68 68 { 69 if( !( user = strchr(line, ':')) || (*user++ = 0) ||70 !( pass = strchr(user, ':')) || (*pass++ = 0) ||71 !(eol = strchr( pass, '\n')) || (*eol++ = 0) )69 if( !(col1 = strchr(line, ':')) || (*col1++ = 0) || 70 !(col2 = strchr(col1, ':')) || (*col2++ = 0) || 71 !(eol = strchr(col2, '\n')) || (*eol++ = 0) ) 72 72 continue; 73 73 74 if( !uh_auth_add(line, user, pass) )74 if( !uh_auth_add(line, col1, col2) ) 75 75 { 76 76 fprintf(stderr, 77 77 "Notice: No password set for user %s, ignoring " 78 "authentication on %s\n", user, line78 "authentication on %s\n", col1, line 79 79 ); 80 80 } … … 82 82 else if( !strncmp(line, "I:", 2) ) 83 83 { 84 if( !( user = strchr(line, ':')) || (*user++ = 0) ||85 !(eol = strchr( user, '\n')) || (*eol++ = 0) )84 if( !(col1 = strchr(line, ':')) || (*col1++ = 0) || 85 !(eol = strchr(col1, '\n')) || (*eol++ = 0) ) 86 86 continue; 87 87 88 conf->index_file = strdup( user);88 conf->index_file = strdup(col1); 89 89 } 90 90 else if( !strncmp(line, "E404:", 5) ) 91 91 { 92 if( !( user = strchr(line, ':')) || (*user++ = 0) ||93 !(eol = strchr( user, '\n')) || (*eol++ = 0) )92 if( !(col1 = strchr(line, ':')) || (*col1++ = 0) || 93 !(eol = strchr(col1, '\n')) || (*eol++ = 0) ) 94 94 continue; 95 95 96 conf->error_handler = strdup(user); 97 } 96 conf->error_handler = strdup(col1); 97 } 98 #ifdef HAVE_CGI 99 else if( (line[0] == '*') && (strchr(line, ':') != NULL) ) 100 { 101 if( !(col1 = strchr(line, '*')) || (*col1++ = 0) || 102 !(col2 = strchr(col1, ':')) || (*col2++ = 0) || 103 !(eol = strchr(col2, '\n')) || (*eol++ = 0) ) 104 continue; 105 106 if( !uh_interpreter_add(col1, col2) ) 107 { 108 fprintf(stderr, 109 "Unable to add interpreter %s for extension %s: " 110 "Out of memory\n", col2, col1 111 ); 112 } 113 } 114 #endif 98 115 } 99 116 … … 111 128 int bound = 0; 112 129 130 int tcp_ka_idl = 1; 131 int tcp_ka_int = 1; 132 int tcp_ka_cnt = 3; 133 113 134 struct listener *l = NULL; 114 135 struct addrinfo *addrs = NULL, *p = NULL; … … 130 151 131 152 /* "address already in use" */ 132 if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)153 if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) ) 133 154 { 134 155 perror("setsockopt()"); 135 156 goto error; 157 } 158 159 /* TCP keep-alive */ 160 if( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) || 161 setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) || 162 setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) || 163 setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)) ) 164 { 165 fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n", 166 strerror(errno)); 136 167 } 137 168 … … 163 194 if( ! (l = uh_listener_add(sock, conf)) ) 164 195 { 165 fprintf(stderr, 166 "uh_listener_add(): Can not create more than " 167 "%i listen sockets\n", UH_LIMIT_LISTENERS 168 ); 169 196 fprintf(stderr, "uh_listener_add(): Failed to allocate memory\n"); 170 197 goto error; 171 198 } … … 344 371 ssize_t rlen = 0; 345 372 346 347 373 memset(buffer, 0, sizeof(buffer)); 348 374 … … 360 386 { 361 387 /* receive data */ 362 rlen = uh_tcp_peek(cl, bufptr, blen);363 364 if( rlen > 0)388 ensure_out(rlen = uh_tcp_peek(cl, bufptr, blen)); 389 390 if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) ) 365 391 { 366 if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) ) 367 { 368 blen -= uh_tcp_recv(cl, bufptr, (int)(idxptr - bufptr) + 4); 369 370 /* header read complete ... */ 371 return uh_http_header_parse(cl, buffer, sizeof(buffer) - blen - 1); 372 } 373 else 374 { 375 rlen = uh_tcp_recv(cl, bufptr, rlen); 376 blen -= rlen; 377 bufptr += rlen; 378 } 392 ensure_out(rlen = uh_tcp_recv(cl, bufptr, 393 (int)(idxptr - bufptr) + 4)); 394 395 /* header read complete ... */ 396 blen -= rlen; 397 return uh_http_header_parse(cl, buffer, 398 sizeof(buffer) - blen - 1); 379 399 } 380 400 else 381 401 { 382 /* invalid request (unexpected eof/timeout) */ 383 uh_http_response(cl, 408, "Request Timeout"); 384 return NULL; 402 ensure_out(rlen = uh_tcp_recv(cl, bufptr, rlen)); 403 404 blen -= rlen; 405 bufptr += rlen; 385 406 } 386 407 } … … 388 409 { 389 410 /* invalid request (unexpected eof/timeout) */ 390 uh_http_response(cl, 408, "Request Timeout");391 411 return NULL; 392 412 } … … 395 415 /* request entity too large */ 396 416 uh_http_response(cl, 413, "Request Entity Too Large"); 417 418 out: 397 419 return NULL; 398 420 } 399 421 422 #if defined(HAVE_LUA) || defined(HAVE_CGI) 400 423 static int uh_path_match(const char *prefix, const char *url) 401 424 { … … 410 433 return 0; 411 434 } 412 413 414 int main (int argc, char **argv) 435 #endif 436 437 static void uh_dispatch_request( 438 struct client *cl, struct http_request *req, struct path_info *pin 439 ) { 440 #ifdef HAVE_CGI 441 struct interpreter *ipr = NULL; 442 443 if( uh_path_match(cl->server->conf->cgi_prefix, pin->name) || 444 (ipr = uh_interpreter_lookup(pin->phys)) ) 445 { 446 uh_cgi_request(cl, req, pin, ipr); 447 } 448 else 449 #endif 450 { 451 uh_file_request(cl, req, pin); 452 } 453 } 454 455 static void uh_mainloop(struct config *conf, fd_set serv_fds, int max_fd) 415 456 { 416 #ifdef HAVE_LUA417 /* Lua runtime */418 lua_State *L = NULL;419 #endif420 421 457 /* master file descriptor list */ 422 fd_set used_fds, serv_fds,read_fds;458 fd_set used_fds, read_fds; 423 459 424 460 /* working structs */ 425 struct addrinfo hints;426 461 struct http_request *req; 427 462 struct path_info *pin; 428 463 struct client *cl; 464 465 /* maximum file descriptor number */ 466 int new_fd, cur_fd = 0; 467 468 /* clear the master and temp sets */ 469 FD_ZERO(&used_fds); 470 FD_ZERO(&read_fds); 471 472 /* backup server descriptor set */ 473 used_fds = serv_fds; 474 475 /* loop */ 476 while(run) 477 { 478 /* create a working copy of the used fd set */ 479 read_fds = used_fds; 480 481 /* sleep until socket activity */ 482 if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 ) 483 { 484 perror("select()"); 485 exit(1); 486 } 487 488 /* run through the existing connections looking for data to be read */ 489 for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ ) 490 { 491 /* is a socket managed by us */ 492 if( FD_ISSET(cur_fd, &read_fds) ) 493 { 494 /* is one of our listen sockets */ 495 if( FD_ISSET(cur_fd, &serv_fds) ) 496 { 497 /* handle new connections */ 498 if( (new_fd = accept(cur_fd, NULL, 0)) != -1 ) 499 { 500 /* add to global client list */ 501 if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL ) 502 { 503 #ifdef HAVE_TLS 504 /* setup client tls context */ 505 if( conf->tls ) 506 conf->tls_accept(cl); 507 #endif 508 509 /* add client socket to global fdset */ 510 FD_SET(new_fd, &used_fds); 511 fd_cloexec(new_fd); 512 max_fd = max(max_fd, new_fd); 513 } 514 515 /* insufficient resources */ 516 else 517 { 518 fprintf(stderr, 519 "uh_client_add(): Cannot allocate memory\n"); 520 521 close(new_fd); 522 } 523 } 524 } 525 526 /* is a client socket */ 527 else 528 { 529 if( ! (cl = uh_client_lookup(cur_fd)) ) 530 { 531 /* this should not happen! */ 532 fprintf(stderr, 533 "uh_client_lookup(): No entry for fd %i!\n", 534 cur_fd); 535 536 goto cleanup; 537 } 538 539 /* parse message header */ 540 if( (req = uh_http_header_recv(cl)) != NULL ) 541 { 542 /* RFC1918 filtering required? */ 543 if( conf->rfc1918_filter && 544 sa_rfc1918(&cl->peeraddr) && 545 !sa_rfc1918(&cl->servaddr) ) 546 { 547 uh_http_sendhf(cl, 403, "Forbidden", 548 "Rejected request from RFC1918 IP " 549 "to public server address"); 550 } 551 else 552 #ifdef HAVE_LUA 553 /* Lua request? */ 554 if( conf->lua_state && 555 uh_path_match(conf->lua_prefix, req->url) ) 556 { 557 conf->lua_request(cl, req, conf->lua_state); 558 } 559 else 560 #endif 561 /* dispatch request */ 562 if( (pin = uh_path_lookup(cl, req->url)) != NULL ) 563 { 564 /* auth ok? */ 565 if( uh_auth_check(cl, req, pin) ) 566 uh_dispatch_request(cl, req, pin); 567 } 568 569 /* 404 */ 570 else 571 { 572 /* Try to invoke an error handler */ 573 pin = uh_path_lookup(cl, conf->error_handler); 574 575 if( pin && uh_auth_check(cl, req, pin) ) 576 { 577 req->redirect_status = 404; 578 uh_dispatch_request(cl, req, pin); 579 } 580 else 581 { 582 uh_http_sendhf(cl, 404, "Not Found", 583 "No such file or directory"); 584 } 585 } 586 } 587 588 #ifdef HAVE_TLS 589 /* free client tls context */ 590 if( conf->tls ) 591 conf->tls_close(cl); 592 #endif 593 594 cleanup: 595 596 /* close client socket */ 597 close(cur_fd); 598 FD_CLR(cur_fd, &used_fds); 599 600 /* remove from global client list */ 601 uh_client_remove(cur_fd); 602 } 603 } 604 } 605 } 606 607 #ifdef HAVE_LUA 608 /* destroy the Lua state */ 609 if( conf->lua_state != NULL ) 610 conf->lua_close(conf->lua_state); 611 #endif 612 } 613 614 615 int main (int argc, char **argv) 616 { 617 /* master file descriptor list */ 618 fd_set used_fds, serv_fds, read_fds; 619 620 /* working structs */ 621 struct addrinfo hints; 429 622 struct sigaction sa; 430 623 struct config conf; … … 434 627 435 628 /* maximum file descriptor number */ 436 int new_fd,cur_fd, max_fd = 0;629 int cur_fd, max_fd = 0; 437 630 438 631 #ifdef HAVE_TLS … … 526 719 527 720 while( (opt = getopt(argc, argv, 528 "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x: t:T:")) > 0721 "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:")) > 0 529 722 ) { 530 723 switch(opt) … … 658 851 case 'x': 659 852 conf.cgi_prefix = optarg; 853 break; 854 855 /* interpreter */ 856 case 'i': 857 if( (optarg[0] == '.') && (port = strchr(optarg, '=')) ) 858 { 859 *port++ = 0; 860 uh_interpreter_add(optarg, port); 861 } 862 else 863 { 864 fprintf(stderr, "Error: Invalid interpreter: %s\n", 865 optarg); 866 exit(1); 867 } 660 868 break; 661 869 #endif … … 741 949 #ifdef HAVE_CGI 742 950 " -x string URL prefix for CGI handler, default is '/cgi-bin'\n" 951 " -i .ext=path Use interpreter at path for files with the given extension\n" 743 952 #endif 744 953 #if defined(HAVE_CGI) || defined(HAVE_LUA) … … 831 1040 conf.lua_prefix = "/lua"; 832 1041 833 L= conf.lua_init(conf.lua_handler);1042 conf.lua_state = conf.lua_init(conf.lua_handler); 834 1043 } 835 1044 } … … 866 1075 } 867 1076 868 /* backup server descriptor set */ 869 used_fds = serv_fds; 870 871 /* loop */ 872 while(run) 873 { 874 /* create a working copy of the used fd set */ 875 read_fds = used_fds; 876 877 /* sleep until socket activity */ 878 if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 ) 879 { 880 perror("select()"); 881 exit(1); 882 } 883 884 /* run through the existing connections looking for data to be read */ 885 for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ ) 886 { 887 /* is a socket managed by us */ 888 if( FD_ISSET(cur_fd, &read_fds) ) 889 { 890 /* is one of our listen sockets */ 891 if( FD_ISSET(cur_fd, &serv_fds) ) 892 { 893 /* handle new connections */ 894 if( (new_fd = accept(cur_fd, NULL, 0)) != -1 ) 895 { 896 /* add to global client list */ 897 if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL ) 898 { 899 #ifdef HAVE_TLS 900 /* setup client tls context */ 901 if( conf.tls ) 902 conf.tls_accept(cl); 903 #endif 904 905 /* add client socket to global fdset */ 906 FD_SET(new_fd, &used_fds); 907 fd_cloexec(new_fd); 908 max_fd = max(max_fd, new_fd); 909 } 910 911 /* insufficient resources */ 912 else 913 { 914 fprintf(stderr, 915 "uh_client_add(): Can not manage more than " 916 "%i client sockets, connection dropped\n", 917 UH_LIMIT_CLIENTS 918 ); 919 920 close(new_fd); 921 } 922 } 923 } 924 925 /* is a client socket */ 926 else 927 { 928 if( ! (cl = uh_client_lookup(cur_fd)) ) 929 { 930 /* this should not happen! */ 931 fprintf(stderr, 932 "uh_client_lookup(): No entry for fd %i!\n", 933 cur_fd); 934 935 goto cleanup; 936 } 937 938 /* parse message header */ 939 if( (req = uh_http_header_recv(cl)) != NULL ) 940 { 941 /* RFC1918 filtering required? */ 942 if( conf.rfc1918_filter && sa_rfc1918(&cl->peeraddr) && 943 !sa_rfc1918(&cl->servaddr) ) 944 { 945 uh_http_sendhf(cl, 403, "Forbidden", 946 "Rejected request from RFC1918 IP to public server address"); 947 } 948 else 949 #ifdef HAVE_LUA 950 /* Lua request? */ 951 if( L && uh_path_match(conf.lua_prefix, req->url) ) 952 { 953 conf.lua_request(cl, req, L); 954 } 955 else 956 #endif 957 /* dispatch request */ 958 if( (pin = uh_path_lookup(cl, req->url)) != NULL ) 959 { 960 /* auth ok? */ 961 if( uh_auth_check(cl, req, pin) ) 962 { 963 #ifdef HAVE_CGI 964 if( uh_path_match(conf.cgi_prefix, pin->name) ) 965 { 966 uh_cgi_request(cl, req, pin); 967 } 968 else 969 #endif 970 { 971 uh_file_request(cl, req, pin); 972 } 973 } 974 } 975 976 /* 404 */ 977 else 978 { 979 /* Try to invoke an error handler */ 980 pin = uh_path_lookup(cl, conf.error_handler); 981 982 if( pin && uh_auth_check(cl, req, pin) ) 983 { 984 req->redirect_status = 404; 985 986 #ifdef HAVE_CGI 987 if( uh_path_match(conf.cgi_prefix, pin->name) ) 988 { 989 uh_cgi_request(cl, req, pin); 990 } 991 else 992 #endif 993 { 994 uh_file_request(cl, req, pin); 995 } 996 } 997 else 998 { 999 uh_http_sendhf(cl, 404, "Not Found", 1000 "No such file or directory"); 1001 } 1002 } 1003 } 1004 1005 #ifdef HAVE_TLS 1006 /* free client tls context */ 1007 if( conf.tls ) 1008 conf.tls_close(cl); 1009 #endif 1010 1011 cleanup: 1012 1013 /* close client socket */ 1014 close(cur_fd); 1015 FD_CLR(cur_fd, &used_fds); 1016 1017 /* remove from global client list */ 1018 uh_client_remove(cur_fd); 1019 } 1020 } 1021 } 1022 } 1077 /* server main loop */ 1078 uh_mainloop(&conf, serv_fds, max_fd); 1023 1079 1024 1080 #ifdef HAVE_LUA 1025 1081 /* destroy the Lua state */ 1026 if( L!= NULL )1027 conf.lua_close( L);1082 if( conf.lua_state != NULL ) 1083 conf.lua_close(conf.lua_state); 1028 1084 #endif 1029 1085 -
branches/backfire/package/uhttpd/src/uhttpd.h
r22590 r22962 29 29 #include <sys/wait.h> 30 30 #include <netinet/in.h> 31 #include <netinet/tcp.h> 31 32 #include <arpa/inet.h> 32 33 #include <linux/limits.h> … … 45 46 #endif 46 47 48 /* uClibc... */ 49 #ifndef SOL_TCP 50 #define SOL_TCP 6 51 #endif 52 47 53 48 54 #define UH_LIMIT_MSGHEAD 4096 49 55 #define UH_LIMIT_HEADERS 64 50 56 51 #define UH_LIMIT_LISTENERS 1652 57 #define UH_LIMIT_CLIENTS 64 53 #define UH_LIMIT_AUTHREALMS 854 58 55 59 #define UH_HTTP_MSG_GET 0 … … 59 63 struct listener; 60 64 struct client; 65 struct interpreter; 61 66 struct http_request; 62 67 … … 77 82 char *lua_prefix; 78 83 char *lua_handler; 84 lua_State *lua_state; 79 85 lua_State * (*lua_init) (const char *handler); 80 86 void (*lua_close) (lua_State *L); … … 106 112 SSL_CTX *tls; 107 113 #endif 114 struct listener *next; 108 115 }; 109 116 … … 118 125 SSL *tls; 119 126 #endif 127 struct client *next; 120 128 }; 121 129 … … 124 132 char user[32]; 125 133 char pass[128]; 134 struct auth_realm *next; 126 135 }; 127 136 … … 141 150 }; 142 151 152 #ifdef HAVE_CGI 153 struct interpreter { 154 char path[PATH_MAX]; 155 char extn[32]; 156 struct interpreter *next; 157 }; 143 158 #endif 144 159 160 #endif 161
Note: See TracChangeset
for help on using the changeset viewer.