Exemplo n.º 1
0
static void
sendFileAsResponse(TSession *const sessionP,
                   TFile *const fileP,
                   const char *const fileName,
                   time_t const fileModTime,
                   MIMEType *const mimeTypeP) {

    uint64_t const filesize = FileSize(fileP);
    const char *const mediatype = MIMETypeGuessFromFile2(mimeTypeP, fileName);

    uint64_t start;  /* Defined only if session has one range */
    uint64_t end;    /* Defined only if session has one range */

    switch (sessionP->ranges.size) {
        case 0:
            ResponseStatus(sessionP, 200);
            break;

        case 1: {
            bool decoded;
            decoded = RangeDecode((char *) (sessionP->ranges.item[0]), filesize,
                                  &start, &end);
            if (!decoded) {
                ListFree(&sessionP->ranges);
                ResponseStatus(sessionP, 200);
            } else {
                const char *contentRange;
                xmlrpc_asprintf(&contentRange,
                                "bytes %" PRIu64 "-%" PRIu64 "/%" PRIu64,
                                start, end, filesize);
                ResponseAddField(sessionP, "Content-range", contentRange);
                xmlrpc_strfree(contentRange);

                ResponseContentLength(sessionP, end - start + 1);
                ResponseStatus(sessionP, 206);
            }
        }
            break;

        default:
            ResponseContentType(sessionP,
                                "multipart/ranges; boundary=" BOUNDARY);
            ResponseStatus(sessionP, 206);
            break;
    }

    if (sessionP->ranges.size == 0) {
        ResponseContentLength(sessionP, filesize);
        ResponseContentType(sessionP, mediatype);
    }

    addLastModifiedHeader(sessionP, fileModTime);

    ResponseWriteStart(sessionP);

    if (sessionP->requestInfo.method != m_head)
        sendBody(sessionP, fileP, filesize, mediatype, start, end);
}
Exemplo n.º 2
0
static void
sendBody(TSession *const sessionP,
         const TFile *const fileP,
         uint64_t const filesize,
         const char *const mediatype,
         uint64_t const start0,
         uint64_t const end0) {
/*----------------------------------------------------------------------------
   'start0' and 'end0' are meaningful only if the session has ranges.
-----------------------------------------------------------------------------*/
    char buffer[4096];

    if (sessionP->ranges.size == 0)
        ConnWriteFromFile(sessionP->connP, fileP, 0, filesize - 1,
                          buffer, sizeof(buffer), 0);
    else if (sessionP->ranges.size == 1)
        ConnWriteFromFile(sessionP->connP, fileP, start0, end0,
                          buffer, sizeof(buffer), 0);
    else {
        uint64_t i;
        for (i = 0; i <= sessionP->ranges.size; ++i) {
            ConnWrite(sessionP->connP, "--", 2);
            ConnWrite(sessionP->connP, BOUNDARY, strlen(BOUNDARY));
            ConnWrite(sessionP->connP, CRLF, 2);

            if (i < sessionP->ranges.size) {
                uint64_t start;
                uint64_t end;
                bool decoded;

                decoded = RangeDecode((char *) (sessionP->ranges.item[i]),
                                      filesize,
                                      &start, &end);
                if (decoded) {
                    /* Entity header, not response header */
                    const char *entityHeader;

                    composeEntityHeader(&entityHeader, mediatype,
                                        start, end, filesize);

                    ConnWrite(sessionP->connP,
                              entityHeader, strlen(entityHeader));

                    xmlrpc_strfree(entityHeader);

                    ConnWriteFromFile(sessionP->connP, fileP, start, end,
                                      buffer, sizeof(buffer), 0);
                }
            }
        }
    }
}
Exemplo n.º 3
0
static void
sendBody(TSession *   const sessionP,
         TFile *      const fileP,
         uint64_t     const filesize,
         const char * const mediatype,
         uint64_t     const start0,
         uint64_t     const end0,
         char *       const z) {

    if (sessionP->ranges.size == 0)
        ConnWriteFromFile(sessionP->conn, fileP, 0, filesize - 1, z, 4096, 0);
    else if (sessionP->ranges.size == 1)
        ConnWriteFromFile(sessionP->conn, fileP, start0, end0, z, 4096, 0);
    else {
        uint64_t i;
        for (i = 0; i <= sessionP->ranges.size; ++i) {
            ConnWrite(sessionP->conn,"--", 2);
            ConnWrite(sessionP->conn, BOUNDARY, strlen(BOUNDARY));
            ConnWrite(sessionP->conn, CRLF, 2);

            if (i < sessionP->ranges.size) {
                uint64_t start;
                uint64_t end;
                abyss_bool decoded;
                    
                decoded = RangeDecode((char *)(sessionP->ranges.item[i]),
                                      filesize,
                                      &start, &end);
                if (decoded) {
                    /* Entity header, not response header */
                    sprintf(z, "Content-type: %s" CRLF
                            "Content-range: bytes %llu-%llu/%llu" CRLF
                            "Content-length: %llu" CRLF
                            CRLF, mediatype, (long long unsigned int)start,
							(long long unsigned int)end,
                            (long long unsigned int)filesize,
							(long long unsigned int)(end-start+1));

                    ConnWrite(sessionP->conn, z, strlen(z));

                    ConnWriteFromFile(sessionP->conn, fileP, start, end, z,
                                      4096, 0);
                }
            }
        }
    }
}
Exemplo n.º 4
0
static abyss_bool
ServerFileHandler(TSession * const r,
                  char *     const z,
                  time_t     const fileModTime,
                  MIMEType * const mimeTypeP) {

    const char * mediatype;
    TFile file;
    uint64_t filesize;
    uint64_t start;
    uint64_t end;
    TDate date;
    char * p;
    TDate filedate;
    
    mediatype = MIMETypeGuessFromFile2(mimeTypeP, z);

    if (!FileOpen(&file,z,O_BINARY | O_RDONLY)) {
        ResponseStatusErrno(r);
        return TRUE;
    }

    fileDate(r, fileModTime, &filedate);

    p = RequestHeaderValue(r, "if-modified-since");
    if (p) {
        if (DateDecode(p,&date)) {
            if (DateCompare(&filedate, &date) <= 0) {
                ResponseStatus(r, 304);
                ResponseWrite(r);
                return TRUE;
            } else
                r->ranges.size = 0;
        }
    }
    filesize = FileSize(&file);

    switch (r->ranges.size) {
    case 0:
        ResponseStatus(r, 200);
        break;

    case 1: {
        abyss_bool decoded;
        decoded = RangeDecode((char *)(r->ranges.item[0]), filesize,
                              &start, &end);
        if (!decoded) {
            ListFree(&(r->ranges));
            ResponseStatus(r, 200);
            break;
        }
        
        sprintf(z, "bytes %llu-%llu/%llu", start, end, filesize);

        ResponseAddField(r, "Content-range", z);
        ResponseContentLength(r, end - start + 1);
        ResponseStatus(r, 206);
    } break;

    default:
        ResponseContentType(r, "multipart/ranges; boundary=" BOUNDARY);
        ResponseStatus(r, 206);
        break;
    }
    
    if (r->ranges.size == 0) {
        ResponseContentLength(r, filesize);
        ResponseContentType(r, mediatype);
    }
    
    if (DateToString(&filedate, z))
        ResponseAddField(r, "Last-Modified", z);

    ResponseWrite(r);

    if (r->request_info.method != m_head)
        sendBody(r, &file, filesize, mediatype, start, end, z);

    FileClose(&file);

    return TRUE;
}