static void
sendDirectoryDocument(TList *      const listP,
                      abyss_bool   const ascending,
                      uint16_t     const sort,
                      abyss_bool   const text,
                      const char * const uri,
                      MIMEType *   const mimeTypeP,
                      TSession *   const sessionP,
                      char *       const z) {

    char *p,z1[26],z2[20],z3[9],u;
    const char * z4;
    int16_t i;
    uint32_t k;

    if (text) {
        sprintf(z, "Index of %s" CRLF, uri);
        i = strlen(z)-2;
        p = z + i + 2;

        while (i > 0) {
            *(p++) = '-';
            --i;
        }

        *p = '\0';
        strcat(z, CRLF CRLF
               "Name                      Size      "
               "Date-Time             Type" CRLF
               "------------------------------------"
               "--------------------------------------------"CRLF);
    } else {
        sprintf(z, "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>"
                "<H1>Index of %s</H1><PRE>",
                uri, uri);
        strcat(z, "Name                      Size      "
               "Date-Time             Type<HR WIDTH=100%>"CRLF);
    }

    HTTPWriteBodyChunk(sessionP, z, strlen(z));

    /* Sort the files */
    qsort(listP->item, listP->size, sizeof(void *),
          (TQSortProc)(sort == 1 ? cmpfilenames : cmpfiledates));
    
    /* Write the listing */
    if (ascending)
        i = 0;
    else
        i = listP->size - 1;

    while ((i < listP->size) && (i >= 0)) {
        TFileInfo * fi;
        struct tm ftm;

        fi = listP->item[i];

        if (ascending)
            ++i;
        else
            --i;
            
        strcpy(z, fi->name);

        k = strlen(z);

        if (fi->attrib & A_SUBDIR) {
            z[k++] = '/';
            z[k] = '\0';
        }

        if (k > 24) {
            z[10] = '\0';
            strcpy(z1, z);
            strcat(z1, "...");
            strcat(z1, z + k - 11);
            k = 24;
            p = z1 + 24;
        } else {
            strcpy(z1, z);
            
            ++k;
            p = z1 + k;
            while (k < 25)
                z1[k++] = ' ';
            
            z1[25] = '\0';
        }

        ftm = *gmtime(&fi->time_write);
        sprintf(z2, "%02u/%02u/%04u %02u:%02u:%02u",ftm.tm_mday,ftm.tm_mon+1,
                ftm.tm_year+1900,ftm.tm_hour,ftm.tm_min,ftm.tm_sec);

        if (fi->attrib & A_SUBDIR) {
            strcpy(z3, "   --  ");
            z4 = "Directory";
        } else {
            if (fi->size < 9999)
                u = 'b';
            else {
                fi->size /= 1024;
                if (fi->size < 9999)
                    u = 'K';
                else {
                    fi->size /= 1024;
                    if (fi->size < 9999)
                        u = 'M';
                    else
                        u = 'G';
                }
            }
                
            sprintf(z3, "%5llu %c", fi->size, u);
            
            if (xmlrpc_streq(fi->name, ".."))
                z4 = "";
            else
                z4 = MIMETypeFromFileName2(mimeTypeP, fi->name);

            if (!z4)
                z4 = "Unknown";
        }

        if (text)
            sprintf(z, "%s%s %s    %s   %s"CRLF, z1, p, z3, z2, z4);
        else
            sprintf(z, "<A HREF=\"%s%s\">%s</A>%s %s    %s   %s"CRLF,
                    fi->name, fi->attrib & A_SUBDIR ? "/" : "",
                    z1, p, z3, z2, z4);

        HTTPWriteBodyChunk(sessionP, z, strlen(z));
    }
        
    /* Write the tail of the file */
    if (text)
        strcpy(z, SERVER_PLAIN_INFO);
    else
        strcpy(z, "</PRE>" SERVER_HTML_INFO "</BODY></HTML>" CRLF CRLF);
    
    HTTPWriteBodyChunk(sessionP, z, strlen(z));
}
const char *
MIMETypeFromFileName(const char * const fileName) {

    return MIMETypeFromFileName2(globalMimeTypeP, fileName);
}