Beispiel #1
0
void MaDir::setPath(char *fileName)
{
	char	buf[MPR_MAX_FNAME];
	int		len;

	mprFree(path);
	mprGetFullPathName(buf, sizeof(buf) - 1, fileName);
	len = strlen(buf);
	if (buf[len - 1] != '/') {
		buf[len] = '/';
		buf[++len] = '\0';
	}
	path = mprStrdup(buf);
	pathLen = strlen(path);

#if WIN
	//
	//	Windows is case insensitive for file names. Always map to lower case.
	//
	mprStrLower(path);
#endif
}
Beispiel #2
0
//
//	Algorithm originally in the GoAhead WebServer.
//
int MaUrl::parse(char *url)
{
	char	*tok, *cp, *portStr, *last_delim, *hostbuf, *portbuf;
	char 	*htmlExt = "html";
	int		c, len, ulen;

	mprAssert(url && *url);

	if (parsedUrlBuf) {
		mprFree(parsedUrlBuf);
	}

	ulen = strlen(url);

	//
	//	Allocate a single buffer to hold all the cracked fields.
	//	Store host, port and url strings (3 nulls).
	//
	len = ulen * 2 + MAX_PORT_LEN + 3;
	parsedUrlBuf = (char*) mprMalloc(len * sizeof(char));
	portbuf = &parsedUrlBuf[len - MAX_PORT_LEN - 1];
	hostbuf = &parsedUrlBuf[ulen+1];
	strcpy(parsedUrlBuf, url);
	url = parsedUrlBuf;

	//
	//	Defaults for missing ULR fields
	//
	strcpy(portbuf, "80");
	portStr = portbuf;
	uri = "/";
	proto = "http";
	host = "localhost";
	query = "";
	ext = htmlExt;

	if (strncmp(url, "http://", 7) == 0) {
		tok = &url[7];
		tok[-3] = '\0';
		proto = url;
		host = tok;
		for (cp = tok; *cp; cp++) {
			if (*cp == '/') {
				break;
			}
			if (*cp == ':') {
				*cp++ = '\0';
				portStr = cp;
				tok = cp;
			}
		}
		if ((cp = strchr(tok, '/')) != NULL) {
			c = *cp;
			*cp = '\0';
			mprStrcpy(hostbuf, ulen + 1, host);
			mprStrcpy(portbuf, MAX_PORT_LEN, portStr);
			*cp = c;
			host = hostbuf;
			portStr = portbuf;
			uri = cp;
			tok = cp;
		}

	} else {
		uri = url;
		tok = url;
	}

	//
	//	Split off the query string.
	//
	if ((cp = strchr(tok, '?')) != NULL) {
		*cp++ = '\0';
		query = cp;
		uri = tok;
		tok = query;
	}

	//
	//	Split off fragment identifier.
	// 
	if ((cp = strchr(tok, '#')) != NULL) {
		*cp++ = '\0';
		if (*query == 0) {
			uri = tok;
		}
	}

	//
	//	FUTURE -- this logic could be improved
	//
	if ((cp = strrchr(uri, '.')) != NULL) {
		if ((last_delim = strrchr(uri, '/')) != NULL) {
			if (last_delim > cp) {
				ext = htmlExt;
			} else {
				ext = cp + 1;
#if WIN
				mprStrLower(ext);
#endif
			}
		} else {
			ext = cp + 1;
#if WIN
			mprStrLower(ext);
#endif
		}
	} else {
		if (uri[strlen(uri) - 1] == '/') {
			ext = htmlExt;
		}
	}

	port = atoi(portStr);
	return 0;
}
Beispiel #3
0
/*
 *  Parse the request headers. Return true if the header parsed.
 */
static bool parseHeaders(MaConn *conn, MaPacket *packet)
{
    MaHostAddress   *address;
    MaRequest       *req;
    MaHost          *host, *hp;
    MaLimits        *limits;
    MprBuf          *content;
    char            keyBuf[MPR_MAX_STRING];
    char            *key, *value, *cp, *tok;
    int             count, keepAlive;

    req = conn->request;
    host = req->host;
    content = packet->content;
    conn->request->headerPacket = packet;
    limits = &conn->http->limits;
    keepAlive = 0;

    strcpy(keyBuf, "HTTP_");
    mprAssert(strstr((char*) content->start, "\r\n"));

    for (count = 0; content->start[0] != '\r' && !conn->connectionFailed; count++) {

        if (count >= limits->maxNumHeaders) {
            maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Too many headers");
            return 0;
        }
        if ((key = getToken(conn, ":")) == 0 || *key == '\0') {
            maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad header format");
            return 0;
        }

        value = getToken(conn, "\r\n");
        while (isspace((int) *value)) {
            value++;
        }
        if (conn->requestFailed) {
            continue;
        }
        mprStrUpper(key);
        for (cp = key; *cp; cp++) {
            if (*cp == '-') {
                *cp = '_';
            }
        }
        mprLog(req, 8, "Key %s, value %s", key, value);
        if (strspn(key, "%<>/\\") > 0) {
            maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad header key value");
            continue;
        }

        /*
         *  Define the header with a "HTTP_" prefix
         */
        mprStrcpy(&keyBuf[5], sizeof(keyBuf) - 5, key);
        mprAddDuplicateHash(req->headers, keyBuf, value);

        switch (key[0]) {
        case 'A':
            if (strcmp(key, "AUTHORIZATION") == 0) {
                value = mprStrdup(req, value);
                req->authType = mprStrTok(value, " \t", &tok);
                req->authDetails = tok;

            } else if (strcmp(key, "ACCEPT_CHARSET") == 0) {
                req->acceptCharset = value;

            } else if (strcmp(key, "ACCEPT") == 0) {
                req->accept = value;

            } else if (strcmp(key, "ACCEPT_ENCODING") == 0) {
                req->acceptEncoding = value;
            }
            break;

        case 'C':
            if (strcmp(key, "CONTENT_LENGTH") == 0) {
                if (req->length >= 0) {
                    maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Mulitple content length headers");
                    continue;
                }
                req->length = mprAtoi(value, 10);
                if (req->length < 0) {
                    maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad content length");
                    continue;
                }
                if (req->length >= host->limits->maxBody) {
                    maFailConnection(conn, MPR_HTTP_CODE_REQUEST_TOO_LARGE, 
                        "Request content length %Ld is too big. Limit %Ld", req->length, host->limits->maxBody);
                    continue;
                }
                mprAssert(req->length >= 0);
                req->remainingContent = req->length;
                req->contentLengthStr = value;

            } else if (strcmp(key, "CONTENT_RANGE") == 0) {
                /*
                 *  This headers specifies the range of any posted body data
                 *  Format is:  Content-Range: bytes n1-n2/length
                 *  Where n1 is first byte pos and n2 is last byte pos
                 */
                char    *sp;
                int     start, end, size;

                start = end = size = -1;
                sp = value;
                while (*sp && !isdigit((int) *sp)) {
                    sp++;
                }
                if (*sp) {
                    start = (int) mprAtoi(sp, 10);

                    if ((sp = strchr(sp, '-')) != 0) {
                        end = (int) mprAtoi(++sp, 10);
                    }
                    if ((sp = strchr(sp, '/')) != 0) {
                        /*
                         *  Note this is not the content length transmitted, but the original size of the input of which 
                         *  the client is transmitting only a portion.
                         */
                        size = (int) mprAtoi(++sp, 10);
                    }
                }
                if (start < 0 || end < 0 || size < 0 || end <= start) {
                    maFailRequest(conn, MPR_HTTP_CODE_RANGE_NOT_SATISFIABLE, "Bad content range");
                    continue;
                }
                req->inputRange = maCreateRange(conn, start, end);

            } else if (strcmp(key, "CONTENT_TYPE") == 0) {
                req->mimeType = value;
                req->form = strstr(value, "application/x-www-form-urlencoded") != 0;

            } else if (strcmp(key, "COOKIE") == 0) {
                if (req->cookie && *req->cookie) {
                    req->cookie = mprStrcat(req, -1, req->cookie, "; ", value, NULL);
                } else {
                    req->cookie = value;
                }

            } else if (strcmp(key, "CONNECTION") == 0) {
                req->connection = value;
                if (mprStrcmpAnyCase(value, "KEEP-ALIVE") == 0) {
                    keepAlive++;

                } else if (mprStrcmpAnyCase(value, "CLOSE") == 0) {
                    conn->keepAliveCount = 0;
                }
                if (!host->keepAlive) {
                    conn->keepAliveCount = 0;
                }
            }
            break;

        case 'F':
            req->forwarded = value;
            break;

        case 'H':
            if (strcmp(key, "HOST") == 0) {
                req->hostName = value;
                address = conn->address;
                if (maIsNamedVirtualHostAddress(address)) {
                    hp = maLookupVirtualHost(address, value);
                    if (hp == 0) {
                        maFailRequest(conn, 404, "No host to serve request. Searching for %s", value);
                        mprLog(conn, 1, "Can't find virtual host %s", value);
                        continue;
                    }
                    req->host = hp;
                    /*
                     *  Reassign this request to a new host
                     */
                    maRemoveConn(host, conn);
                    host = hp;
                    conn->host = hp;
                    maAddConn(hp, conn);
                }
            }
            break;

        case 'I':
            if ((strcmp(key, "IF_MODIFIED_SINCE") == 0) || (strcmp(key, "IF_UNMODIFIED_SINCE") == 0)) {
                MprTime     newDate = 0;
                char        *cp;
                bool        ifModified = (key[3] == 'M');

                if ((cp = strchr(value, ';')) != 0) {
                    *cp = '\0';
                }
                if (mprParseTime(conn, &newDate, value, MPR_UTC_TIMEZONE, NULL) < 0) {
                    mprAssert(0);
                    break;
                }
                if (newDate) {
                    setIfModifiedDate(conn, newDate, ifModified);
                    req->flags |= MA_REQ_IF_MODIFIED;
                }

            } else if ((strcmp(key, "IF_MATCH") == 0) || (strcmp(key, "IF_NONE_MATCH") == 0)) {
                char    *word, *tok;
                bool    ifMatch = key[3] == 'M';

                if ((tok = strchr(value, ';')) != 0) {
                    *tok = '\0';
                }
                req->ifMatch = ifMatch;
                req->flags |= MA_REQ_IF_MODIFIED;

                value = mprStrdup(conn, value);
                word = mprStrTok(value, " ,", &tok);
                while (word) {
                    addMatchEtag(conn, word);
                    word = mprStrTok(0, " ,", &tok);
                }

            } else if (strcmp(key, "IF_RANGE") == 0) {
                char    *word, *tok;

                if ((tok = strchr(value, ';')) != 0) {
                    *tok = '\0';
                }
                req->ifMatch = 1;
                req->flags |= MA_REQ_IF_MODIFIED;

                value = mprStrdup(conn, value);
                word = mprStrTok(value, " ,", &tok);
                while (word) {
                    addMatchEtag(conn, word);
                    word = mprStrTok(0, " ,", &tok);
                }
            }
            break;

        case 'P':
            if (strcmp(key, "PRAGMA") == 0) {
                req->pragma = value;
            }
            break;

        case 'R':
            if (strcmp(key, "RANGE") == 0) {
                if (!parseRange(conn, value)) {
                    maFailRequest(conn, MPR_HTTP_CODE_RANGE_NOT_SATISFIABLE, "Bad range");
                }
            } else if (strcmp(key, "REFERER") == 0) {
                /* NOTE: yes the header is misspelt in the spec */
                req->referer = value;
            }
            break;

        case 'T':
            if (strcmp(key, "TRANSFER_ENCODING") == 0) {
                mprStrLower(value);
                if (strcmp(value, "chunked") == 0) {
                    req->flags |= MA_REQ_CHUNKED;
                    /*
                     *  This will be revised by the chunk filter as chunks are processed and will be set to zero when the
                     *  last chunk has been received.
                     */
                    req->remainingContent = MAXINT;
                }
            }
            break;
        
#if BLD_DEBUG
        case 'X':
            if (strcmp(key, "X_APPWEB_CHUNK_SIZE") == 0) {
                mprStrUpper(value);
                conn->response->chunkSize = atoi(value);
                if (conn->response->chunkSize <= 0) {
                    conn->response->chunkSize = 0;
                } else if (conn->response->chunkSize > conn->http->limits.maxChunkSize) {
                    conn->response->chunkSize = conn->http->limits.maxChunkSize;
                }
            }
            break;
#endif

        case 'U':
            if (strcmp(key, "USER_AGENT") == 0) {
                req->userAgent = value;
            }
            break;
        }
    }
    if (conn->protocol == 0 && !keepAlive) {
        conn->keepAliveCount = 0;
    }
    if (!(req->flags & MA_REQ_CHUNKED)) {
        /*  
         *  Step over "\r\n" after headers. As an optimization, don't do this if chunked so chunking can parse a single
         *  chunk delimiter of "\r\nSIZE ...\r\n"
         */
        mprAdjustBufStart(content, 2);
    }
    mprLog(conn, 3, "Select host \"%s\"", conn->host->name);

    if (maSetRequestUri(conn, req->url, "") < 0) {
        maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad URI format");
        return 0;
    }
    if (conn->host->secure) {
        req->parsedUri->scheme = mprStrdup(req, "https");
    }
    req->parsedUri->port = conn->sock->port;
    req->parsedUri->host = req->hostName ? req->hostName : conn->host->name;
    return 1;
}
Beispiel #4
0
/*
 *  Parse a complete URI. This accepts full URIs with schemes (http:) and partial URLs
 */
MprUri *mprParseUri(MprCtx ctx, cchar *uri)
{
    MprUri  *up;
    char    *tok, *cp, *last_delim, *hostbuf, *urlTok;
    int     c, len, ulen, http;

    mprAssert(uri);

    up = mprAllocObj(ctx, MprUri);
    if (up == 0) {
        return 0;
    }

    /*
     *  Allocate a single buffer to hold all the cracked fields.
     */
    ulen = (int) strlen(uri);
    len = ulen * 2 + 3;

    up->originalUri = mprStrdup(up, uri);
    up->parsedUriBuf = (char*) mprAlloc(up, len * (int) sizeof(char));

    hostbuf = &up->parsedUriBuf[ulen+1];
    strcpy(up->parsedUriBuf, uri);
    urlTok = up->parsedUriBuf;

    /*
     *  Defaults for missing URL fields
     */
    up->url = "/";
    up->scheme = "http";
    up->host = "localhost";
    up->port = 80;
    up->query = 0;
    up->ext = 0;
    up->secure = 0;
    up->reference = 0;

    http = 0;
    tok = 0;

    if (strncmp(urlTok, "https://", 8) == 0) {
        up->secure = 1;
        up->port = 443;
        tok = &urlTok[8];
        http++;

    } else if (strncmp(urlTok, "http://", 7) == 0) {
        tok = &urlTok[7];
        http++;
    }

    if (http) {
        up->scheme = urlTok;
        up->host = tok;
        tok[-3] = '\0';
        for (cp = tok; *cp; cp++) {
            if (*cp == '/') {
                break;
            }
            if (*cp == ':') {
                *cp++ = '\0';
                up->port = atoi(cp);
                tok = cp;
            }
        }
        if ((cp = strchr(tok, '/')) != NULL) {
            c = *cp;
            *cp = '\0';
            mprStrcpy(hostbuf, ulen + 1, up->host);
            *cp = c;
            up->host = hostbuf;
            up->url = cp;
            tok = cp;
        }

    } else {
        up->url = urlTok;
        tok = urlTok;
    }

    if ((cp = strchr(tok, '#')) != NULL) {
        *cp++ = '\0';
        up->reference = cp;
        tok = cp;
    }
    if ((cp = strchr(tok, '?')) != NULL) {
        *cp++ = '\0';
        up->query = cp;
        tok = up->query;
    }

    if ((cp = strrchr(up->url, '.')) != NULL) {
        if ((last_delim = strrchr(up->url, '/')) != NULL) {
            if (last_delim <= cp) {
                up->ext = cp + 1;
#if UNUSED && BLD_WIN_LIKE
                mprStrLower(up->ext);
#endif
            }
        } else {
            up->ext = cp + 1;
#if UNUSED && BLD_WIN_LIKE
            mprStrLower(up->ext);
#endif
        }
    } else {
        len = (int) strlen(up->url);
    }

    return up;
}
Beispiel #5
0
/*
    Parse the CGI output headers. 
    Sample CGI program:

    Content-type: text/html
   
    <html.....
 */
static bool parseHeader(MaConn *conn, MprCmd *cmd)
{
    MaResponse      *resp;
    MaQueue         *q;
    MprBuf          *buf;
    char            *endHeaders, *headers, *key, *value, *location;
    int             fd, len;

    resp = conn->response;
    location = 0;
    value = 0;

    buf = mprGetCmdBuf(cmd, MPR_CMD_STDOUT);
    mprAddNullToBuf(buf);
    headers = mprGetBufStart(buf);

    /*
        Split the headers from the body.
     */
    len = 0;
    fd = mprGetCmdFd(cmd, MPR_CMD_STDOUT);
    if ((endHeaders = strstr(headers, "\r\n\r\n")) == NULL) {
        if ((endHeaders = strstr(headers, "\n\n")) == NULL) {
            if (fd >= 0 && strlen(headers) < MA_MAX_HEADERS) {
                /* Not EOF and less than max headers and have not yet seen an end of headers delimiter */
                return 0;
            }
        } else len = 2;
    } else {
        len = 4;
    }
    if (endHeaders) {
        endHeaders[len - 1] = '\0';
        endHeaders += len;
    }

    /*
        Want to be tolerant of CGI programs that omit the status line.
     */
    if (strncmp((char*) buf->start, "HTTP/1.", 7) == 0) {
        if (!parseFirstCgiResponse(conn, cmd)) {
            /* maFailConnection already called */
            return 0;
        }
    }
    
    if (endHeaders && strchr(mprGetBufStart(buf), ':')) {
        mprLog(conn, 4, "CGI: parseHeader: header\n%s", headers);

        while (mprGetBufLength(buf) > 0 && buf->start[0] && (buf->start[0] != '\r' && buf->start[0] != '\n')) {

            if ((key = getCgiToken(buf, ":")) == 0) {
                maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad header format");
                return 0;
            }
            value = getCgiToken(buf, "\n");
            while (isspace((int) *value)) {
                value++;
            }
            len = (int) strlen(value);
            while (len > 0 && (value[len - 1] == '\r' || value[len - 1] == '\n')) {
                value[len - 1] = '\0';
                len--;
            }
            mprStrLower(key);

            if (strcmp(key, "location") == 0) {
                location = value;

            } else if (strcmp(key, "status") == 0) {
                maSetResponseCode(conn, atoi(value));

            } else if (strcmp(key, "content-type") == 0) {
                maSetResponseMimeType(conn, value);

            } else if (strcmp(key, "content-length") == 0) {
                maSetEntityLength(conn, (MprOff) mprAtoi(value, 10));
                resp->chunkSize = 0;

            } else {
                /*
                    Now pass all other headers back to the client
                 */
                maSetHeader(conn, 0, key, "%s", value);
            }
        }
        buf->start = endHeaders;
    }
    if (location) {
        maRedirect(conn, resp->code, location);
        q = resp->queue[MA_QUEUE_SEND].nextQ;
        maPutForService(q, maCreateEndPacket(q), 1);
    }
    cmd->userFlags |= MA_CGI_SEEN_HEADER;
    return 1;
}
Beispiel #6
0
/*
 *  Parse the appweb.conf directives for authorization
 */
static int parseAuth(MaHttp *http, cchar *key, char *value, MaConfigState *state)
{
    MaServer    *server;
    MaHost      *host;
    MaAuth      *auth;
    MaAcl       acl;
    char        *path, *names, *tok, *type, *aclSpec;

    server = state->server;
    host = state->host;
    auth = state->auth;

    if (mprStrcmpAnyCase(key, "AuthGroupFile") == 0) {
        path = maMakePath(host, mprStrTrim(value, "\""));
        if (maReadGroupFile(server, auth, path) < 0) {
            mprError(http, "Can't open AuthGroupFile %s", path);
            return MPR_ERR_BAD_SYNTAX;
        }
        mprFree(path);
        return 1;

    } else if (mprStrcmpAnyCase(key, "AuthMethod") == 0) {
        value = mprStrTrim(value, "\"");
        if (mprStrcmpAnyCase(value, "pam") == 0) {
            auth->method = MA_AUTH_METHOD_PAM;
            return 1;

        } else if (mprStrcmpAnyCase(value, "file") == 0) {
            auth->method = MA_AUTH_METHOD_FILE;
            return 1;

        } else {
            return MPR_ERR_BAD_SYNTAX;
        }

    } else if (mprStrcmpAnyCase(key, "AuthName") == 0) {
        maSetAuthRealm(auth, mprStrTrim(value, "\""));
        return 1;
        
    } else if (mprStrcmpAnyCase(key, "AuthType") == 0) {
        value = mprStrTrim(value, "\"");
        if (mprStrcmpAnyCase(value, "Basic") == 0) {
            auth->type = MA_AUTH_BASIC;

        } else if (mprStrcmpAnyCase(value, "None") == 0) {
            auth->type = 0;

#if BLD_FEATURE_AUTH_DIGEST
        } else if (mprStrcmpAnyCase(value, "Digest") == 0) {
            auth->type = MA_AUTH_DIGEST;
#endif

        } else {
            mprError(http, "Unsupported authorization protocol");
            return MPR_ERR_BAD_SYNTAX;
        }
        return 1;
        
    } else if (mprStrcmpAnyCase(key, "AuthUserFile") == 0) {
        path = maMakePath(host, mprStrTrim(value, "\""));
        if (maReadUserFile(server, auth, path) < 0) {
            mprError(http, "Can't open AuthUserFile %s", path);
            return MPR_ERR_BAD_SYNTAX;
        }
        mprFree(path);
        return 1;

#if BLD_FEATURE_AUTH_DIGEST
    } else if (mprStrcmpAnyCase(key, "AuthDigestQop") == 0) {
        value = mprStrTrim(value, "\"");
        mprStrLower(value);
        if (strcmp(value, "none") != 0 && strcmp(value, "auth") != 0 && strcmp(value, "auth-int") != 0) {
            return MPR_ERR_BAD_SYNTAX;
        }
        maSetAuthQop(auth, value);
        return 1;

    } else if (mprStrcmpAnyCase(key, "AuthDigestAlgorithm") == 0) {
        return 1;

    } else if (mprStrcmpAnyCase(key, "AuthDigestDomain") == 0) {
        return 1;

    } else if (mprStrcmpAnyCase(key, "AuthDigestNonceLifetime") == 0) {
        return 1;

#endif
    } else if (mprStrcmpAnyCase(key, "Require") == 0) {
        if (maGetConfigValue(http, &type, value, &tok, 1) < 0) {
            return MPR_ERR_BAD_SYNTAX;
        }
        if (mprStrcmpAnyCase(type, "acl") == 0) {
            aclSpec = mprStrTrim(tok, "\"");
            acl = maParseAcl(auth, aclSpec);
            maSetRequiredAcl(auth, acl);

        } else if (mprStrcmpAnyCase(type, "valid-user") == 0) {
            maSetAuthAnyValidUser(auth);

        } else {
            names = mprStrTrim(tok, "\"");
            if (mprStrcmpAnyCase(type, "user") == 0) {
                maSetAuthRequiredUsers(auth, names);

            } else if (mprStrcmpAnyCase(type, "group") == 0) {
                maSetAuthRequiredGroups(auth, names);

            } else {
                mprError(http, "Bad Require syntax: %s", type);
                return MPR_ERR_BAD_SYNTAX;
            }
        }
        return 1;
    }
    return 0;
}
Beispiel #7
0
void MaCgiHandler::parseHeader(MaRequest *rq)
{
	MaDataStream	*dynBuf;
	char			*endHeaders, *header, *key, *value, *tok;
	char			*cp, *lp, *saveHeader;
	int				len;

	header = headerBuf->getStart();
	endHeaders = strstr(header, "\r\n\r\n");
	if (endHeaders == 0) {
		endHeaders = strstr(header, "\n\n");
		if (endHeaders == 0) {
			endHeaders = strstr(header, "\r\r\n\r\r\n");
			if (endHeaders == 0) {
				return;
			}
		}
		headerBuf->adjustStart(endHeaders + 2 - header);
	} else {
		headerBuf->adjustStart(endHeaders + 4 - header);
	}
	*endHeaders = '\0';

	mprLog(5, log, "%d: parseHeader: header\n%s\n", rq->getFd(), header);

	if (endHeaders) {
		lp = header;
		tok = lp;
		while (tok && *tok) {

			for (cp = tok; *cp && *cp != '\r' && *cp != '\n'; cp++) 
				;
			len = cp - tok + 1;
			mprAssert(len >= 0);

			mprAllocMemcpy(&saveHeader, len, tok, len);
			saveHeader[len - 1] = '\0';

			if ((key = mprStrTok(lp, ": \t\r\n", &tok)) == 0) {
				break;
			}
			lp = 0;

			if ((value = mprStrTok(0, "\r\n", &tok)) == 0) {
				rq->requestError(503, "Bad header format");
				rq->finishRequest();
				mprFree(saveHeader);
				return;
			}
			while (isspace((uchar) *value)) {
				value++;
			}
			mprStrLower(key);

			if (strcmp(key, "location") == 0) {
				mprFree(newLocation);
				newLocation = mprStrdup(value);

			} else if (strcmp(key, "status") == 0) {
				rq->setResponseCode(atoi(value));

			} else if (strcmp(key, "content-type") == 0) {
				rq->setResponseMimeType(value);

#if OLD
			} else if ((key[0] == 'x' || key[0] == 'X') && key[1] == '-') {
				//
				//	Pass "X-Headers" through to the client
				//
				rq->setHeader(saveHeader);
			}
#endif
			} else {
				//
				//	Now pass all other headers back to the client
				//
				rq->setHeader(saveHeader);
			}
			mprFree(saveHeader);
		}
Beispiel #8
0
int MaClient::parseHeader(char *line)
{
	char	*key, *value, *tok, *tp;

	mprAssert(line && *line);

	if ((key = mprStrTok(line, ": \t\n", &tok)) == 0) {
		formatError("Bad HTTP header");
		responseCode = MPR_HTTP_CLIENT_ERROR;
		finishRequest(1);
		return MPR_ERR_BAD_STATE;
	}
	if ((value = mprStrTok(0, "\n", &tok)) == 0) {
		value = "";
	}
	while (isspace((uchar) *value)) {
		value++;
	}

	//	Upper to be consistent with Request?
	mprStrLower(key);
	headerValues->insert(new MprStringHashEntry(key, value));

	if (strcmp("www-authenticate", key) == 0) {
		tp = value;
		while (*value && !isspace((uchar) *value)) {
			value++;
		}
		*value++ = '\0';
		mprStrLower(tp);
		mprFree(serverAuthType);
		serverAuthType = mprStrdup(tp);

		if (parseAuthenticate(value) < 0) {
			formatError("Bad Authenticate header");
			responseCode = MPR_HTTP_CLIENT_ERROR;
			finishRequest(1);
			return MPR_ERR_BAD_STATE;
		}

	} else if (strcmp("content-length", key) == 0) {
		contentLength = atoi(value);
		if (mprStrCmpAnyCase(method, "HEAD") != 0) {
			contentRemaining = atoi(value);
		}

	} else if (strcmp("connection", key) == 0) {
		mprStrLower(value);
		if (strcmp(value, "close") == 0) {
			flags &= ~MPR_HTTP_KEEP_ALIVE;
#if BLD_FEATURE_KEEP_ALIVE
		} else if (strcmp(value, "keep-alive") == 0) {
			if (userFlags & MPR_HTTP_KEEP_ALIVE) {
				flags |= MPR_HTTP_KEEP_ALIVE;
			}
#endif
		}
	} else if (strcmp("transfer-encoding", key) == 0) {
		mprStrLower(value);
		if (strcmp(value, "chunked") == 0) {
			flags |= MPR_HTTP_INPUT_CHUNKED;
		}
	}
	return 0;
}