diff --git a/upnphttp.c b/upnphttp.c index 215cd4d..b5db9a1 100644 --- a/upnphttp.c +++ b/upnphttp.c @@ -150,7 +150,7 @@ ParseHttpHeaders(struct upnphttp * h) if(strncasecmp(line, "Content-Length", 14)==0) { p = colon; - while(*p < '0' || *p > '9') + while(*p && (*p < '0' || *p > '9')) p++; h->req_contentlen = atoi(p); } @@ -160,14 +160,14 @@ ParseHttpHeaders(struct upnphttp * h) n = 0; while(*p == ':' || *p == ' ' || *p == '\t') p++; - while(p[n]>=' ') - { + while(p[n] >= ' ') n++; - } - if((p[0] == '"' && p[n-1] == '"') - || (p[0] == '\'' && p[n-1] == '\'')) + if(n >= 2 && + ((p[0] == '"' && p[n-1] == '"') || + (p[0] == '\'' && p[n-1] == '\''))) { - p++; n -= 2; + p++; + n -= 2; } h->req_soapAction = p; h->req_soapActionLen = n; @@ -175,10 +175,10 @@ ParseHttpHeaders(struct upnphttp * h) else if(strncasecmp(line, "Callback", 8)==0) { p = colon; - while(*p != '<' && *p != '\r' ) + while(*p && *p != '<' && *p != '\r' ) p++; n = 0; - while(p[n] != '>' && p[n] != '\r' ) + while(p[n] && p[n] != '>' && p[n] != '\r' ) n++; h->req_Callback = p + 1; h->req_CallbackLen = MAX(0, n - 1); @@ -200,7 +200,7 @@ ParseHttpHeaders(struct upnphttp * h) while(isspace(*p)) p++; n = 0; - while(!isspace(p[n])) + while(p[n] && !isspace(p[n])) n++; h->req_SID = p; h->req_SIDLen = n; @@ -212,7 +212,7 @@ ParseHttpHeaders(struct upnphttp * h) while(isspace(*p)) p++; n = 0; - while(!isspace(p[n])) + while(p[n] && !isspace(p[n])) n++; h->req_NT = p; h->req_NTLen = n; @@ -396,8 +396,11 @@ ParseHttpHeaders(struct upnphttp * h) } } next_header: - while(!(line[0] == '\r' && line[1] == '\n')) - line++; + line = strstr(line, "\r\n"); + if (!line) + { + return; + } line += 2; } if( h->reqflags & FLAG_CHUNKED ) @@ -410,9 +413,10 @@ next_header: (h->req_chunklen = strtol(line, &endptr, 16)) && (endptr != line) ) { - while(!(endptr[0] == '\r' && endptr[1] == '\n')) + endptr = strstr(endptr, "\r\n"); + if (!endptr) { - endptr++; + return; } line = endptr+h->req_chunklen+2; } @@ -541,18 +545,6 @@ Send501(struct upnphttp * h) CloseSocket_upnphttp(h); } -static const char * -findendheaders(const char * s, int len) -{ - while(len-- > 0) - { - if(s[0]=='\r' && s[1]=='\n' && s[2]=='\r' && s[3]=='\n') - return s; - s++; - } - return NULL; -} - /* Sends the description generated by the parameter */ static void sendXMLdesc(struct upnphttp * h, char * (f)(int *)) @@ -807,7 +799,7 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h) p = h->req_buf; if(!p) return; - for(i = 0; i<15 && *p != ' ' && *p != '\r'; i++) + for(i = 0; i<15 && *p && *p != ' ' && *p != '\r'; i++) HttpCommand[i] = *(p++); HttpCommand[i] = '\0'; while(*p==' ') @@ -818,13 +810,13 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h) while(*p!='/') p++; } - for(i = 0; i<511 && *p != ' ' && *p != '\r'; i++) + for(i = 0; i<511 && *p && *p != ' ' && *p != '\r'; i++) HttpUrl[i] = *(p++); HttpUrl[i] = '\0'; while(*p==' ') p++; HttpVer = h->HttpVer; - for(i = 0; i<15 && *p != '\r'; i++) + for(i = 0; i<15 && *p && *p != '\r'; i++) HttpVer[i] = *(p++); HttpVer[i] = '\0'; /*DPRINTF(E_INFO, L_HTTP, "HTTP REQUEST : %s %s (%s)\n", @@ -846,6 +838,11 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h) /* see if we need to wait for remaining data */ if( (h->reqflags & FLAG_CHUNKED) ) { + if( h->req_chunklen == -1) + { + Send400(h); + return; + } if( h->req_chunklen ) { h->state = 2; @@ -856,9 +853,11 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h) while( (h->req_chunklen = strtol(chunk, &endptr, 16)) && (endptr != chunk) ) { - while(!(endptr[0] == '\r' && endptr[1] == '\n')) + endptr = strstr(endptr, "\r\n"); + if (!endptr) { - endptr++; + Send400(h); + return; } endptr += 2; @@ -1071,7 +1070,7 @@ Process_upnphttp(struct upnphttp * h) h->req_buflen += n; h->req_buf[h->req_buflen] = '\0'; /* search for the string "\r\n\r\n" */ - endheaders = findendheaders(h->req_buf, h->req_buflen); + endheaders = strstr(h->req_buf, "\r\n\r\n"); if(endheaders) { h->req_contentoff = endheaders - h->req_buf + 4; @@ -1143,56 +1142,43 @@ BuildHeader_upnphttp(struct upnphttp * h, int respcode, time_t curtime = time(NULL); char date[30]; int templen; + struct string_s res; if(!h->res_buf) { templen = sizeof(httpresphead) + 256 + bodylen; h->res_buf = (char *)malloc(templen); h->res_buf_alloclen = templen; } - h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen, - httpresphead, "HTTP/1.1", - respcode, respmsg, - (h->respflags&FLAG_HTML)?"text/html":"text/xml; charset=\"utf-8\"", + res.data = h->res_buf; + res.size = h->res_buf_alloclen; + res.off = 0; + strcatf(&res, httpresphead, "HTTP/1.1", + respcode, respmsg, + (h->respflags&FLAG_HTML)?"text/html":"text/xml; charset=\"utf-8\"", bodylen); /* Additional headers */ if(h->respflags & FLAG_TIMEOUT) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Timeout: Second-"); + strcatf(&res, "Timeout: Second-"); if(h->req_Timeout) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "%d\r\n", h->req_Timeout); + strcatf(&res, "%d\r\n", h->req_Timeout); } else { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "300\r\n"); + strcatf(&res, "300\r\n"); } } if(h->respflags & FLAG_SID) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "SID: %.*s\r\n", h->req_SIDLen, h->req_SID); + strcatf(&res, "SID: %.*s\r\n", h->req_SIDLen, h->req_SID); } if(h->reqflags & FLAG_LANGUAGE) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Content-Language: en\r\n"); + strcatf(&res, "Content-Language: en\r\n"); } strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime)); - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Date: %s\r\n", date); - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "EXT:\r\n"); + strcatf(&res, "Date: %s\r\n", date); + strcatf(&res, "EXT:\r\n"); #if 0 // DLNA - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "contentFeatures.dlna.org: \r\n"); + strcatf(&res, "contentFeatures.dlna.org: \r\n"); #endif - h->res_buf[h->res_buflen++] = '\r'; - h->res_buf[h->res_buflen++] = '\n'; + strcatf(&res, "\r\n"); + h->res_buflen = res.off; if(h->res_buf_alloclen < (h->res_buflen + bodylen)) { h->res_buf = (char *)realloc(h->res_buf, (h->res_buflen + bodylen)); @@ -1524,6 +1510,7 @@ SendResp_thumbnail(struct upnphttp * h, char * object) if( access(path, F_OK) != 0 ) { DPRINTF(E_ERROR, L_HTTP, "Error accessing %s\n", path); + Send404(h); sqlite3_free(path); return; }