Exemple #1
0
abyss_bool
ResponseWriteStart(TSession * const sessionP) {
/*----------------------------------------------------------------------------
   Begin the process of sending the response for an HTTP transaction
   (i.e. Abyss session).

   As part of this, send the entire HTTP header for the response.
-----------------------------------------------------------------------------*/
    struct _TServer * const srvP = ConnServer(sessionP->connP)->srvP;

    assert(!sessionP->responseStarted);

    if (sessionP->status == 0) {
        /* Handler hasn't set status.  That's an error */
        TraceMsg("Abyss client called ResponseWriteStart() on "
                 "a session for which he has not set the request status "
                 "('status' member of TSession).  Using status 500\n");
        sessionP->status = 500;
    }

    sessionP->responseStarted = TRUE;

    {
        const char * const reason = HTTPReasonByStatus(sessionP->status);
        const char * line;
		abyss_bool ret = TRUE;
        xmlrpc_asprintf(&line,"HTTP/1.1 %u %s\r\n", sessionP->status, reason);
        ret = ConnWrite(sessionP->connP, line, strlen(line));
        xmlrpc_strfree(line);
		if (!ret) return FALSE;
    }


    addConnectionHeaderFld(sessionP);

    if (sessionP->chunkedwrite && sessionP->chunkedwritemode)
        ResponseAddField(sessionP, "Transfer-Encoding", "chunked");

    addDateHeaderFld(sessionP);

    if (srvP->advertise)
        addServerHeaderFld(sessionP);

    /* Note that sessionP->responseHeaderFields is defined to contain
       syntactically but not necessarily semantically valid header
       field names and values.
    */
    if (sendHeader(sessionP->connP, sessionP->responseHeaderFields))
		if (ConnWrite(sessionP->connP, "\r\n", 2))
			return TRUE;

	return FALSE;
}
static void
addConnectionHeaderFld(TSession * const sessionP) {

    struct _TServer * const srvP = ConnServer(sessionP->connP)->srvP;

    if (HTTPKeepalive(sessionP)) {
        const char * keepaliveValue;
        
        ResponseAddField(sessionP, "Connection", "Keep-Alive");

        xmlrpc_asprintf(&keepaliveValue, "timeout=%u, max=%u",
                        srvP->keepalivetimeout, srvP->keepalivemaxconn);

        ResponseAddField(sessionP, "Keep-Alive", keepaliveValue);

        xmlrpc_strfree(keepaliveValue);
    } else
        ResponseAddField(sessionP, "Connection", "close");
}
static abyss_bool
ServerDefaultHandlerFunc(TSession * const sessionP) {

    struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP;

    char *p;
    char z[4096];
    TFileStat fs;
    unsigned int i;
    abyss_bool endingslash=FALSE;

    if (!RequestValidURIPath(sessionP)) {
        ResponseStatus(sessionP, 400);
        return TRUE;
    }

    /* Must check for * (asterisk uri) in the future */
    if (sessionP->request_info.method == m_options) {
        ResponseAddField(sessionP, "Allow", "GET, HEAD");
        ResponseContentLength(sessionP, 0);
        ResponseStatus(sessionP, 200);
        return TRUE;
    }

    if ((sessionP->request_info.method != m_get) &&
        (sessionP->request_info.method != m_head)) {
        ResponseAddField(sessionP, "Allow", "GET, HEAD");
        ResponseStatus(sessionP, 405);
        return TRUE;
    }

    strcpy(z, srvP->filespath);
    strcat(z, sessionP->request_info.uri);

    p = z + strlen(z) - 1;
    if (*p == '/') {
        endingslash = TRUE;
        *p = '\0';
    }

#ifdef WIN32
    p = z;
    while (*p) {
        if ((*p) == '/')
            *p= '\\';

        ++p;
    }
#endif  /* WIN32 */

    if (!FileStat(z, &fs)) {
        ResponseStatusErrno(sessionP);
        return TRUE;
    }

    if (fs.st_mode & S_IFDIR) {
        /* Redirect to the same directory but with the ending slash
        ** to avoid problems with some browsers (IE for examples) when
        ** they generate relative urls */
        if (!endingslash) {
            strcpy(z, sessionP->request_info.uri);
            p = z+strlen(z);
            *p = '/';
            *(p+1) = '\0';
            ResponseAddField(sessionP, "Location", z);
            ResponseStatus(sessionP, 302);
            ResponseWrite(sessionP);
            return TRUE;
        }

        *p = DIRECTORY_SEPARATOR[0];
        ++p;

        i = srvP->defaultfilenames.size;
        while (i-- > 0) {
            *p = '\0';        
            strcat(z, (srvP->defaultfilenames.item[i]));
            if (FileStat(z, &fs)) {
                if (!(fs.st_mode & S_IFDIR))
                    return ServerFileHandler(sessionP, z, fs.st_mtime,
                                             srvP->mimeTypeP);
            }
        }

        *(p-1) = '\0';
        
        if (!FileStat(z, &fs)) {
            ResponseStatusErrno(sessionP);
            return TRUE;
        }
        return ServerDirectoryHandler(sessionP, z, fs.st_mtime,
                                      srvP->mimeTypeP);
    } else
        return ServerFileHandler(sessionP, z, fs.st_mtime,
                                 srvP->mimeTypeP);
}