Annotation of libwww/Library/src/HTFWrite.c, revision 2.35

2.1       frystyk     1: /*                                                                 HTFWrite.c
                      2: **     FILE WRITER
                      3: **
2.6       frystyk     4: **     (c) COPYRIGHT MIT 1995.
2.1       frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
2.35    ! frystyk     6: **     @(#) $Id: HTFWrite.c,v 2.34 1996/06/08 01:52:07 frystyk Exp $
2.1       frystyk     7: **
                      8: **     This version of the stream object just writes to a C file.
                      9: **     The file is assumed open and left open.
                     10: **
                     11: **     Bugs:
                     12: **             strings written must be less than buffer size.
                     13: **
                     14: **      History:
                     15: **         HFN: wrote it
                     16: **         HWL: converted the caching scheme to be hierachical by taking
                     17: **              AL code from Deamon
2.10      frystyk    18: **        HFN: moved cache code to HTCache module
2.1       frystyk    19: **
                     20: */
                     21: 
                     22: /* Library include files */
2.28      frystyk    23: #include "sysdep.h"
2.35    ! frystyk    24: #include "WWWUtil.h"
2.1       frystyk    25: #include "HTFormat.h"
2.21      frystyk    26: #include "HTError.h"
2.1       frystyk    27: #include "HTAlert.h"
2.19      frystyk    28: #include "HTAccess.h"
2.35    ! frystyk    29: #include "HTLib.h"
2.4       frystyk    30: #include "HTBind.h"
2.3       frystyk    31: #include "HTParse.h"
2.15      frystyk    32: #include "HTReq.h"
2.3       frystyk    33: #include "HTFWrite.h"                                   /* Implemented here */
2.1       frystyk    34: 
2.4       frystyk    35: #define HASH_SIZE 1001         /* Tunable */
                     36: 
2.3       frystyk    37: struct _HTStream {
2.28      frystyk    38:     const HTStreamClass *isa;
2.24      frystyk    39:     
                     40:     FILE *             fp;
2.31      frystyk    41:     BOOL               leave_open;                 /* Close file when free? */
2.24      frystyk    42:     char *             end_command;                   /* Command to execute */
                     43:     BOOL               remove_on_close;                     /* Remove file? */
                     44:     char *             filename;                            /* Name of file */
                     45:     HTRequest *                request;                       /* saved for callback */
                     46:     HTRequestCallback *        callback;
2.3       frystyk    47: };
2.1       frystyk    48: 
2.3       frystyk    49: /* ------------------------------------------------------------------------- */
2.1       frystyk    50: 
2.16      frystyk    51: PRIVATE int HTFWriter_put_character (HTStream * me, char c)
2.3       frystyk    52: {
                     53:     return (fputc(c, me->fp) == EOF) ? HT_ERROR : HT_OK;
                     54: }
                     55: 
2.28      frystyk    56: PRIVATE int HTFWriter_put_string (HTStream * me, const char* s)
2.3       frystyk    57: {
                     58:     if (*s)                                         /* For vms :-( 10/04-94 */
                     59:        return (fputs(s, me->fp) == EOF) ? HT_ERROR : HT_OK;
                     60:     return HT_OK;
                     61: }
                     62: 
2.16      frystyk    63: PRIVATE int HTFWriter_flush (HTStream * me)
2.3       frystyk    64: {
2.7       frystyk    65:     return (fflush(me->fp) == EOF) ? HT_ERROR : HT_OK;
2.3       frystyk    66: }
                     67: 
2.28      frystyk    68: PRIVATE int HTFWriter_write (HTStream * me, const char* s, int l)
2.3       frystyk    69: {
2.7       frystyk    70:     int status ;
                     71:     status = (fwrite(s, 1, l, me->fp) != l) ? HT_ERROR : HT_OK ;
2.24      frystyk    72:     if (l > 1 && status == HT_OK) (void) HTFWriter_flush(me);
2.7       frystyk    73:     return status ;
2.3       frystyk    74: }
2.7       frystyk    75: 
2.30      frystyk    76: PRIVATE int HTFWriter_free (HTStream * me)
2.3       frystyk    77: {
2.24      frystyk    78:     if (me) {
                     79:        if (me->leave_open != YES) fclose(me->fp);
2.28      frystyk    80: #ifdef HAVE_SYSTEM
2.24      frystyk    81:        if (me->end_command) system(me->end_command);    /* SECURITY HOLE!!! */
2.17      frystyk    82: #endif
2.24      frystyk    83:        if (me->remove_on_close) REMOVE(me->filename);
                     84:        if (me->callback) (*me->callback)(me->request, me->filename);
2.26      frystyk    85:        HT_FREE(me->end_command);
                     86:        HT_FREE(me->filename);
                     87:        HT_FREE(me);
2.3       frystyk    88:     }
                     89:     return HT_OK;
                     90: }
                     91: 
2.18      frystyk    92: PRIVATE int HTFWriter_abort (HTStream * me, HTList * e)
2.3       frystyk    93: {
2.27      eric       94:     if (STREAM_TRACE) HTTrace("FileWriter.. ABORTING...\n");
2.24      frystyk    95:     if (me) {
                     96:        if (me->leave_open != YES) fclose(me->fp);
                     97:        if (me->remove_on_close) REMOVE(me->filename);
2.26      frystyk    98:        HT_FREE(me->end_command);
                     99:        HT_FREE(me->filename);
                    100:        HT_FREE(me);
2.3       frystyk   101:     }
                    102:     return HT_ERROR;
                    103: }
                    104: 
2.28      frystyk   105: PRIVATE const HTStreamClass HTFWriter = /* As opposed to print etc */
2.3       frystyk   106: {              
                    107:     "FileWriter",
                    108:     HTFWriter_flush,
2.30      frystyk   109:     HTFWriter_free,
2.3       frystyk   110:     HTFWriter_abort,
                    111:     HTFWriter_put_character,
                    112:     HTFWriter_put_string,
                    113:     HTFWriter_write
                    114: };
                    115: 
2.24      frystyk   116: PUBLIC HTStream * HTFWriter_new (HTRequest * request, FILE * fp,
                    117:                                 BOOL leave_open)
2.3       frystyk   118: {
2.24      frystyk   119:     HTStream * me = NULL;
2.3       frystyk   120:     if (!fp) {
2.27      eric      121:        if (STREAM_TRACE)HTTrace("FileWriter.. Bad file descriptor\n");
2.24      frystyk   122:        return HTErrorStream();
2.3       frystyk   123:     }
2.26      frystyk   124:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    125:         HT_OUTOFMEM("HTFWriter_new");
2.3       frystyk   126:     me->isa = &HTFWriter;       
                    127:     me->fp = fp;
2.24      frystyk   128:     me->leave_open = leave_open;
                    129:     me->request = request;
2.3       frystyk   130:     return me;
                    131: }
                    132: 
                    133: /* ------------------------------------------------------------------------- */
                    134: /*                          FILE WRITER ROUTINES                            */
                    135: /* ------------------------------------------------------------------------- */
                    136: 
2.4       frystyk   137: /*
                    138: **   This function tries really hard to find a non-existent filename relative
2.31      frystyk   139: **   to the path given. Returns a string that must be freed by the caller or
2.4       frystyk   140: **   NULL on error. The base must be '/' terminated which!
                    141: */
2.28      frystyk   142: PRIVATE char *get_filename (char * base, const char * url, const char * suffix)
2.4       frystyk   143: {
                    144:     char *path=NULL;
                    145:     char filename[40];
                    146:     int hash=0;
                    147: 
                    148:     /* Do this until we find a name that doesn't exist */
                    149:     while (1)
                    150:     {
2.28      frystyk   151:        const char *ptr=url;
2.4       frystyk   152:        for( ; *ptr; ptr++)
                    153:            hash = (int) ((hash * 31 + (* (unsigned char *) ptr)) % HASH_SIZE);
                    154: 
2.28      frystyk   155: #ifdef HAVE_GETPID
2.4       frystyk   156:        sprintf(filename, "%d-%d", hash, (int) getpid());
                    157: #else
                    158:        sprintf(filename, "%d-%d", hash, time(NULL));
                    159: #endif
                    160:        StrAllocCopy(path, base);
                    161:        StrAllocCat(path, filename);
                    162:        if (suffix) StrAllocCat(path, suffix);
                    163: 
                    164:        {
                    165:            FILE *fp = fopen(path, "r");
                    166:            if (fp)                          /* This file does already exist */
                    167:                fclose(fp);
                    168:            else
                    169:                break;                                  /* Got the file name */
                    170:        }
                    171:     }
2.34      frystyk   172:     if (STREAM_TRACE) HTTrace("Save file... Temporaray file `%s\'\n", path);
2.4       frystyk   173:     return path;
                    174: }
                    175: 
                    176: 
2.24      frystyk   177: /*     Save Locally
                    178: **     ------------
                    179: **     Saves a file to local disk. This can for example be used to dump
                    180: **     date objects of unknown media types to local disk. The stream prompts
                    181: **     for a file name for the temporary file.
2.1       frystyk   182: */
2.24      frystyk   183: PUBLIC HTStream* HTSaveLocally (HTRequest *    request,
                    184:                                void *          param,
                    185:                                HTFormat        input_format,
                    186:                                HTFormat        output_format,
                    187:                                HTStream *      output_stream)
2.1       frystyk   188: {
2.24      frystyk   189:     FILE * fp = NULL;
                    190:     char * filename = NULL;
2.33      frystyk   191:     HTUserProfile * up = HTRequest_userProfile(request);
                    192:     char * tmproot = HTUserProfile_tmp(up);
2.19      frystyk   193:     if (HTLib_secure()) {
2.21      frystyk   194:        HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
2.24      frystyk   195:                           NULL, 0, "HTSaveLocally");
                    196:        return HTErrorStream();
2.1       frystyk   197:     }
2.33      frystyk   198:     if (!tmproot) {
2.27      eric      199:        if (STREAM_TRACE) HTTrace("Save File... turned off");
2.24      frystyk   200:        return HTErrorStream();
2.1       frystyk   201:     }
                    202:        
2.24      frystyk   203:     /* Let's prompt the user for a file name for this file */
2.4       frystyk   204:     {
2.24      frystyk   205:        HTAlertCallback *cbf = HTAlert_find(HT_A_PROMPT);
2.13      frystyk   206:        HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
                    207:        char *suffix = HTBind_getSuffix(anchor);
2.33      frystyk   208:        char *deflt = get_filename(tmproot,HTAnchor_physical(anchor),suffix);
2.24      frystyk   209:        if (cbf) {
                    210:            HTAlertPar * reply = HTAlert_newReply();
                    211:            if ((*cbf)(request, HT_A_PROMPT, HT_MSG_FILENAME,deflt,NULL,reply))
                    212:                filename = HTAlert_replyMessage(reply);
                    213:            HTAlert_deleteReply(reply);
                    214:        }
2.26      frystyk   215:        HT_FREE(suffix);
                    216:        HT_FREE(deflt);
2.24      frystyk   217:        if (filename) {
                    218:            if ((fp = fopen(filename, "wb")) == NULL) {
                    219:                HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
                    220:                                   filename, strlen(filename),"HTSaveLocally");
2.26      frystyk   221:                HT_FREE(filename);
2.24      frystyk   222:                return HTErrorStream();
                    223:            }
                    224:        } else {
2.27      eric      225:            if (STREAM_TRACE) HTTrace("Save File... No file name\n");
2.24      frystyk   226:            return HTErrorStream();
2.4       frystyk   227:        }
                    228:     }
2.24      frystyk   229:     
                    230:     /* Now we are ready for creating the file writer stream */
                    231:     if (fp) {
                    232:        HTStream * me = HTFWriter_new(request, fp, NO);
                    233:        me->filename = filename;
                    234:        return me;
2.1       frystyk   235:     }
2.26      frystyk   236:     HT_FREE(filename);
2.24      frystyk   237:     return HTErrorStream();
2.1       frystyk   238: }
                    239: 
                    240: 
2.24      frystyk   241: /*     Take action using a system command
                    242: **     ----------------------------------
                    243: **     Creates temporary file, writes to it and then executes system
                    244: **     command (maybe an external viewer) when EOF has been reached. The
                    245: **     stream finds a suitable name of the temporary file which preserves the
                    246: **     suffix. This way, the system command can find out the file type from
                    247: **     the name of the temporary file name.
2.1       frystyk   248: */
2.24      frystyk   249: PUBLIC HTStream* HTSaveAndExecute (HTRequest * request,
                    250:                                   void *       param,
                    251:                                   HTFormat     input_format,
                    252:                                   HTFormat     output_format,
                    253:                                   HTStream *   output_stream)
2.1       frystyk   254: {
2.24      frystyk   255:     FILE * fp = NULL;
                    256:     char * filename = NULL;
2.33      frystyk   257:     HTUserProfile * up = HTRequest_userProfile(request);
                    258:     char * tmproot = HTUserProfile_tmp(up);
2.19      frystyk   259:     if (HTLib_secure()) {
2.21      frystyk   260:        HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
                    261:                           NULL, 0, "HTSaveLocally");
2.24      frystyk   262:        return HTErrorStream();
2.1       frystyk   263:     }
2.33      frystyk   264:     if (!tmproot) {
2.27      eric      265:        if (STREAM_TRACE) HTTrace("Save File... turned off");
2.24      frystyk   266:        return HTErrorStream();
2.1       frystyk   267:     }
                    268:        
2.24      frystyk   269:     /* Let's find a hash name for this file without asking user */
2.4       frystyk   270:     {
2.13      frystyk   271:        HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
                    272:        char *suffix = HTBind_getSuffix(anchor);
2.33      frystyk   273:        filename = get_filename(tmproot, HTAnchor_physical(anchor), suffix);
2.26      frystyk   274:        HT_FREE(suffix);
2.25      frystyk   275:        if (filename) {
                    276:            if ((fp = fopen(filename, "wb")) == NULL) {
                    277:                HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
                    278:                                   filename, strlen(filename),"HTSaveAndExecute");
2.26      frystyk   279:                HT_FREE(filename);
2.25      frystyk   280:                return HTErrorStream();
                    281:            }
                    282:        } else {
2.27      eric      283:            if (STREAM_TRACE) HTTrace("Save File... No file name\n");
2.24      frystyk   284:            return HTErrorStream();
2.4       frystyk   285:        }
                    286:     }
                    287:     
2.24      frystyk   288:     /* Now we are ready for creating the file writer stream */
                    289:     if (fp) {
                    290:        HTStream * me = HTFWriter_new(request, fp, NO);
                    291:        me->filename = filename;
2.31      frystyk   292:        if (param) {
                    293:            if ((me->end_command = (char  *) HT_MALLOC((strlen((char *) param) + 10 + 3*strlen(filename)))) == NULL)
                    294:                HT_OUTOFMEM("SaveAndExecute");
                    295:            sprintf (me->end_command,
                    296:                     (char *)param, filename, filename, filename);
                    297:        }
2.24      frystyk   298:        return me;
2.1       frystyk   299:     }
2.26      frystyk   300:     HT_FREE(filename);
2.24      frystyk   301:     return HTErrorStream();
2.1       frystyk   302: }
                    303: 
                    304: 
                    305: /*     Save and Call Back
                    306: **     ------------------
2.32      frystyk   307: **     This stream works exactly like the HTSaveAndExecute
2.24      frystyk   308: **     stream but in addition when EOF has been reached, it checks whether a
                    309: **     callback function has been associated with the request object in which
                    310: **     case, this callback is being called. This can be use by the
                    311: **     application to do some processing after the system command
                    312: **     has terminated. The callback function is called with the file name of
                    313: **     the temporary file as parameter.
2.1       frystyk   314: */
2.16      frystyk   315: PUBLIC HTStream* HTSaveAndCallback (HTRequest *                request,
                    316:                                    void *              param,
                    317:                                    HTFormat            input_format,
                    318:                                    HTFormat            output_format,
                    319:                                    HTStream *          output_stream)
2.1       frystyk   320: {
2.24      frystyk   321:     HTStream * me = HTSaveAndExecute(request, param, input_format,
                    322:                                     output_format, output_stream);
                    323:     if (me) {
                    324:        me->callback = HTRequest_callback(request);
                    325:        return me;
                    326:     }
                    327:     return HTErrorStream();
2.1       frystyk   328: }
                    329: 

Webmaster