home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
- /*
- * state machine to handle local file and directory URL's
- * and to retreive file cache objects
- *
- * Designed and implemented by Lou Montulli '94
- */
-
- #include "mkutils.h"
- #include "mkgeturl.h"
- #include "mkstream.h"
- #include "mkformat.h"
- #include "mkparse.h"
- #include "mkftp.h"
- #include "mkfsort.h"
- #include "mkfile.h"
- #include "merrors.h"
- #include "glhist.h"
-
- #include "il_strm.h" /* Image Lib stream converters. */
- #include "libimg.h" /* Image Lib public API. */
-
- #if defined(XP_WIN) || defined(XP_OS2)
- #include "errno.h"
- #endif
-
- #include "xp_error.h"
- #include "prefapi.h"
-
- /* for XP_GetString() */
- #include "xpgetstr.h"
- extern int XP_ALERT_OUTMEMORY;
- extern int XP_PROGRESS_DIRDONE;
- extern int XP_PROGRESS_FILEDONE;
- extern int XP_PROGRESS_FILEZEROLENGTH;
- extern int XP_PROGRESS_READDIR;
- extern int XP_PROGRESS_READFILE;
- extern int MK_OUT_OF_MEMORY;
- extern int MK_UNABLE_TO_LOCATE_FILE;
- extern int MK_UNABLE_TO_OPEN_FILE;
- extern int MK_ZERO_LENGTH_FILE;
- extern int MK_UNABLE_TO_DELETE_FILE;
- extern int MK_UNABLE_TO_DELETE_DIRECTORY;
- extern int MK_MKDIR_FILE_ALREADY_EXISTS;
- extern int MK_COULD_NOT_CREATE_DIRECTORY;
- extern int MK_ERROR_WRITING_FILE;
- extern int MK_NOT_A_DIRECTORY;
- extern int XP_READING_SEGMENT;
- extern int XP_TITLE_DIRECTORY_LISTING;
- extern int XP_H1_DIRECTORY_LISTING;
- extern int XP_UPTO_HIGHER_LEVEL_DIRECTORY;
- extern int XP_TITLE_DIRECTORY_OF_ETC;
-
- /* states of the machine
- */
- typedef enum {
- NET_CHECK_FILE_TYPE,
- NET_DELETE_FILE,
- NET_MOVE_FILE,
- NET_PUT_FILE,
- NET_MAKE_DIRECTORY,
- NET_FILE_SETUP_STREAM,
- NET_OPEN_FILE,
- NET_SETUP_FILE_STREAM,
- NET_OPEN_DIRECTORY,
- NET_READ_FILE_CHUNK,
- NET_READ_DIRECTORY_CHUNK,
- NET_BEGIN_PRINT_DIRECTORY,
- NET_PRINT_DIRECTORY,
- NET_FILE_DONE,
- NET_FILE_ERROR_DONE,
- NET_FILE_FREE
- } net_FileStates;
-
- /* forward decl */
- PRIVATE int32 net_ProcessFile (ActiveEntry * cur_entry);
-
- /* allow URL byterange requests for backwards compatibility,
- * but only leave this in for a short while
- */
- #define URL_BYTERANGE_METHOD
-
- #define DIR_STRUCT struct dirent
-
- typedef struct _FILEConData {
- XP_File file_ptr;
- XP_Dir dir_ptr;
- net_FileStates next_state;
- NET_StreamClass * stream;
- char * filename;
- Bool is_dir;
- SortStruct * sort_base;
- Bool pause_for_read;
- Bool is_cache_file;
- Bool calling_netlib_all_the_time;
- Bool destroy_graph_progress; /* do we need to destroy graph progress? */
- int32 original_content_length; /* the content length at the time of
- * calling graph progress
- */
- char * byterange_string;
- int32 range_length; /* the length of the current byte range */
- } FILEConData;
-
- #define CD_FILE_PTR connection_data->file_ptr
- #define CD_DIR_PTR connection_data->dir_ptr
- #define CD_NEXT_STATE connection_data->next_state
- #define CD_STREAM connection_data->stream
- #define CD_FILENAME connection_data->filename
- #define CD_IS_DIR connection_data->is_dir
- #define CD_SORT_BASE connection_data->sort_base
- #define CD_PAUSE_FOR_READ connection_data->pause_for_read
- #define CD_IS_CACHE_FILE connection_data->is_cache_file
-
- #define CE_WINDOW_ID cur_entry->window_id
- #define CE_URL_S cur_entry->URL_s
- #define CE_STATUS cur_entry->status
- #define CE_SOCK cur_entry->socket
- #define CE_BYTES_RECEIVED cur_entry->bytes_received
- #define CE_FORMAT_OUT cur_entry->format_out
- #define CD_DESTROY_GRAPH_PROGRESS connection_data->destroy_graph_progress
- #define CD_ORIGINAL_CONTENT_LENGTH connection_data->original_content_length
- #define CD_BYTERANGE_STRING connection_data->byterange_string
- #define CD_RANGE_LENGTH connection_data->range_length
-
- #define PUTS(s) (*connection_data->stream->put_block) \
- (connection_data->stream, s, XP_STRLEN(s))
- #define IS_WRITE_READY (*connection_data->stream->is_write_ready) \
- (connection_data->stream)
- #define PUTB(b,l) (*connection_data->stream->put_block) \
- (connection_data->stream, b, l)
- #define COMPLETE_STREAM (*connection_data->stream->complete) \
- (connection_data->stream)
- #define ABORT_STREAM(s) (*connection_data->stream->abort) \
- (connection_data->stream, s)
-
- /* try and open the URL path as a normal file
- * if it fails set the next state to try and open
- * a directory.
- */
- PRIVATE int
- net_check_file_type (ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
- XP_StatStruct stat_entry;
-
- TRACEMSG(("Looking for file: %s", CD_FILENAME));
-
- /* larubbio added xpSARCache check */
- if(-1 == XP_Stat (CD_FILENAME,
- &stat_entry,
- CD_IS_CACHE_FILE ?
- (CE_URL_S->ext_cache_file ?
- (CE_URL_S->SARCache ? xpSARCache : xpExtCache) : xpCache) : xpURL))
- {
- if(CE_URL_S->method == URL_PUT_METHOD)
- {
- CD_NEXT_STATE = NET_PUT_FILE;
- return(0);
- }
- else if(CE_URL_S->method == URL_MKDIR_METHOD)
- {
- CD_NEXT_STATE = NET_MAKE_DIRECTORY;
- return(0);
- }
-
-
- CE_URL_S->error_msg = NET_ExplainErrorDetails(
- MK_UNABLE_TO_LOCATE_FILE,
- *CD_FILENAME ? CD_FILENAME : "/");
- return(MK_UNABLE_TO_LOCATE_FILE);
- }
-
- if(!CD_IS_CACHE_FILE)
- {
- CE_URL_S->last_modified = stat_entry.st_mtime;
- }
-
- if(S_ISDIR(stat_entry.st_mode))
- {
- /* if the current address doesn't end with a
- * slash, add it now.
- */
- if(CE_URL_S->address[XP_STRLEN(CE_URL_S->address)-1] != '/')
- StrAllocCat(CE_URL_S->address, "/");
-
- CE_URL_S->is_directory = TRUE;
- CD_IS_DIR = TRUE;
- }
- else
- {
- CE_URL_S->content_length = (int32) stat_entry.st_size;
- }
-
- if(CD_IS_CACHE_FILE)
- {
- /* if we are looking for a cache file then
- * we are always looking to do a GET of
- * the file regardless of the method in
- * the URL_s
- */
- CD_NEXT_STATE = NET_FILE_SETUP_STREAM;
- }
- else switch(CE_URL_S->method)
- {
- case URL_PUT_METHOD:
- {
- char * msg;
- msg = PR_smprintf("Overwrite file %s?", CD_FILENAME);
- if(FE_Confirm(CE_WINDOW_ID, msg))
- CD_NEXT_STATE = NET_PUT_FILE;
- else
- CD_NEXT_STATE = NET_FILE_DONE;
- }
- break;
-
- case URL_MKDIR_METHOD:
- /* error, can't create a directory over
- * an existing file or directory
- */
- CE_URL_S->error_msg = NET_ExplainErrorDetails(
- MK_MKDIR_FILE_ALREADY_EXISTS,
- CD_FILENAME);
- return(MK_MKDIR_FILE_ALREADY_EXISTS);
-
- case URL_HEAD_METHOD:
- /* we just need the relavent file info.
- * it is currently filled into the URL struct
- */
- CD_NEXT_STATE = NET_FILE_DONE;
- break;
-
- case URL_MOVE_METHOD:
- CD_NEXT_STATE = NET_MOVE_FILE;
- break;
-
- case URL_DELETE_METHOD:
- CD_NEXT_STATE = NET_DELETE_FILE;
- break;
-
- case URL_GET_METHOD:
- CD_NEXT_STATE = NET_FILE_SETUP_STREAM;
- break;
-
- case URL_INDEX_METHOD:
- if(!CE_URL_S->is_directory)
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_NOT_A_DIRECTORY, CD_FILENAME);
- return(MK_NOT_A_DIRECTORY);
- }
- CD_NEXT_STATE = NET_FILE_SETUP_STREAM;
- break;
-
- default:
- XP_ASSERT(0);
- CD_NEXT_STATE = NET_FILE_DONE;
- break;
- }
-
- return(0);
- }
-
- PRIVATE int
- net_delete_file (ActiveEntry * ce)
- {
- #ifndef LIVEWIRE
- XP_ASSERT(0);
- return(MK_OUT_OF_MEMORY);
-
- #else
- FILEConData * cd = (FILEConData *) ce->con_data;
-
- TRACEMSG(("Deleteing file: %s", cd->filename));
-
- if(cd->is_dir)
- {
- if(0 != XP_RemoveDirectory(cd->filename, xpURL))
- {
- /* error */
- ce->URL_s->error_msg = NET_ExplainErrorDetails(
- MK_UNABLE_TO_DELETE_DIRECTORY,
- cd->filename);
- return(MK_UNABLE_TO_DELETE_DIRECTORY);
- }
- }
- else
- {
- if(0 != XP_FileRemove(cd->filename, xpURL))
- {
- /* error */
- ce->URL_s->error_msg = NET_ExplainErrorDetails(
- MK_UNABLE_TO_DELETE_FILE,
- cd->filename);
- return(MK_UNABLE_TO_DELETE_FILE);
- }
- }
-
- /* success */
- cd->next_state = NET_FILE_DONE;
- return(0);
- #endif /* NOT LIVEWIRE */
- }
-
- PRIVATE int
- net_move_file (ActiveEntry * ce)
- {
- #ifndef LIVEWIRE
- XP_ASSERT(0);
- return(MK_OUT_OF_MEMORY);
-
- #else
- FILEConData * cd = (FILEConData *) ce->con_data;
- char *destination;
-
- XP_ASSERT(ce->URL_s->destination);
- if(!ce->URL_s->destination)
- return(MK_UNABLE_TO_LOCATE_FILE);
-
- destination = NET_ParseURL(ce->URL_s->destination, GET_PATH_PART);
-
- if(!destination)
- return(MK_OUT_OF_MEMORY);
-
- TRACEMSG(("Moving file: %s", cd->filename));
-
- if(0 != XP_FileRename(cd->filename, xpURL, destination, xpURL))
- {
- /* error! */
- XP_ASSERT(0);
- /* @@@@@ */
- return(MK_UNABLE_TO_LOCATE_FILE);
- }
-
- /* success */
- cd->next_state = NET_FILE_DONE;
- return(0);
- #endif /* !LIVEWIRE */
- }
-
- PRIVATE int
- net_put_file (ActiveEntry * ce)
- {
- #ifndef LIVEWIRE
- XP_ASSERT(0);
- return(MK_OUT_OF_MEMORY);
-
- #else
- FILEConData * cd = (FILEConData *) ce->con_data;
- XP_File fp;
- int status;
-
- if(!(fp = XP_FileOpen(cd->filename, xpURL, XP_FILE_WRITE_BIN)))
- {
- /* error */
- ce->URL_s->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_OPEN_FILE,
- cd->filename);
- return(MK_UNABLE_TO_OPEN_FILE);
- }
-
- XP_ASSERT(ce->URL_s->post_data);
- XP_ASSERT(!ce->URL_s->post_data_is_file);
-
- status = XP_FileWrite(ce->URL_s->post_data, ce->URL_s->post_data_size, fp);
-
- XP_FileClose(fp);
-
- if(status < ce->URL_s->post_data_size)
- {
- /* error */
- ce->URL_s->error_msg = NET_ExplainErrorDetails(MK_FILE_WRITE_ERROR,
- cd->filename);
- return(MK_FILE_WRITE_ERROR);
- }
-
- /* success */
- cd->next_state = NET_FILE_DONE;
- return(0);
- #endif /* !LIVEWIRE */
- }
-
- PRIVATE int
- net_make_directory (ActiveEntry * ce)
- {
- #ifndef LIVEWIRE
- XP_ASSERT(0);
- return(MK_OUT_OF_MEMORY);
-
- #else
- FILEConData * cd = (FILEConData *) ce->con_data;
-
- if(0 != XP_MakeDirectory(cd->filename, xpURL))
- {
- /* error */
- ce->URL_s->error_msg = NET_ExplainErrorDetails(
- MK_COULD_NOT_CREATE_DIRECTORY,
- cd->filename);
- return(MK_COULD_NOT_CREATE_DIRECTORY);
- }
-
- /* success */
- cd->next_state = NET_FILE_DONE;
- return (0);
- #endif /* !LIVEWIRE */
- }
-
- /* setup the output stream
- */
- PRIVATE int
- net_file_setup_stream(ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
-
- if(CD_IS_DIR)
- {
- char * pUrl ;
- int status;
-
- status = PREF_CopyCharPref("protocol.mimefor.file",&pUrl);
-
- if (status >= 0 && pUrl) {
- StrAllocCopy(CE_URL_S->content_type, pUrl);
- XP_FREE(pUrl);
- } else {
- StrAllocCopy(CE_URL_S->content_type, APPLICATION_HTTP_INDEX);
- }
-
- CD_STREAM = NET_StreamBuilder(CE_FORMAT_OUT, CE_URL_S, CE_WINDOW_ID);
-
- if(!CD_STREAM)
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_CONVERT);
- return(MK_UNABLE_TO_CONVERT);
- }
-
- #ifdef MOZILLA_CLIENT
- GH_UpdateGlobalHistory(CE_URL_S);
- #endif /* MOZILLA_CLIENT */
-
- CD_NEXT_STATE = NET_OPEN_DIRECTORY;
- }
- else
- {
- /*
- * don't open the stream yet for files
- */
- CD_NEXT_STATE = NET_OPEN_FILE;
- }
-
- return(0); /* OK */
- }
-
- PRIVATE int
- net_open_file (ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
-
- TRACEMSG(("MKFILE: Trying to open: %s\n",CD_FILENAME));
-
- if((CD_FILE_PTR = XP_FileOpen(CD_FILENAME,
- (CD_IS_CACHE_FILE ?
- (CE_URL_S->ext_cache_file ?
- (CE_URL_S->SARCache ? xpSARCache : xpExtCache) : xpCache) : xpURL),
- XP_FILE_READ_BIN)) != NULL)
- {
- CD_NEXT_STATE = NET_READ_FILE_CHUNK;
- }
- else
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_OPEN_FILE,
- CD_FILENAME);
-
- /* if errno is equal to "Too many open files"
- * return a special error
- */
- #ifndef XP_MAC
- if(errno == EMFILE)
- return(MK_TOO_MANY_OPEN_FILES);
- else
- #endif
- return(MK_UNABLE_TO_OPEN_FILE);
- }
-
- if (!CE_URL_S->load_background)
- NET_Progress(CE_WINDOW_ID, XP_GetString(XP_PROGRESS_READFILE));
-
- /* CE_SOCK = XP_Fileno(CD_FILE_PTR); */
- CE_SOCK = NULL;
- cur_entry->local_file = TRUE;
- NET_SetFileReadSelect(CE_WINDOW_ID, XP_Fileno(CD_FILE_PTR));
-
- /* @@@ now that we have determined that it is a local file
- * set URL_s->cache_file so that the streams think
- * that this file came from the cache
- */
- StrAllocCopy(CE_URL_S->cache_file, CD_FILENAME);
-
- CD_PAUSE_FOR_READ = TRUE;
-
- CD_NEXT_STATE = NET_SETUP_FILE_STREAM;
-
- if (!CE_URL_S->load_background) {
- FE_GraphProgressInit(CE_WINDOW_ID, CE_URL_S, CE_URL_S->content_length);
- CD_DESTROY_GRAPH_PROGRESS = TRUE; /* we will need to destroy it */
- }
- CD_ORIGINAL_CONTENT_LENGTH = CE_URL_S->content_length;
-
- return(0); /* ok */
- }
-
-
- #ifdef MOZILLA_CLIENT
- #ifdef MOZ_MAIL_NEWS
- extern int net_InitializeNewsFeData (ActiveEntry * cur_entry);
- extern int IMAP_InitializeImapFeData (ActiveEntry * cur_entry);
- #endif /* MOZ_MAIL_NEWS */
- #endif /* MOZILLA_CLIENT */
-
- PRIVATE int
- net_setup_file_stream (ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
- int32 count;
-
- /* set up the stream now
- */
- TRACEMSG(("Trying to look at content type: %s",CE_URL_S->content_type));
- if(!CE_URL_S->content_type)
- {
- int img_type;
-
- /* read the first chunk of the file
- */
- count = XP_FileRead(NET_Socket_Buffer, NET_Socket_Buffer_Size, CD_FILE_PTR);
-
- if(!count)
- {
- NET_ClearFileReadSelect(CE_WINDOW_ID, XP_Fileno(CD_FILE_PTR));
- NET_Progress(CE_WINDOW_ID, XP_GetString(XP_PROGRESS_FILEZEROLENGTH));
- XP_FileClose(CD_FILE_PTR);
- CE_SOCK = NULL;
- CD_FILE_PTR = 0;
- CD_NEXT_STATE = NET_FILE_ERROR_DONE;
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_ZERO_LENGTH_FILE,
- CD_FILENAME);
- return(MK_ZERO_LENGTH_FILE);
- }
-
- #ifdef MOZILLA_CLIENT
- img_type = IL_Type(NET_Socket_Buffer, count);
- if (img_type && img_type != IL_NOTFOUND)
- {
- switch(img_type)
- {
- case IL_GIF:
- StrAllocCopy(CE_URL_S->content_type, IMAGE_GIF);
- break;
- case IL_XBM:
- StrAllocCopy(CE_URL_S->content_type, IMAGE_XBM);
- break;
- case IL_JPEG:
- StrAllocCopy(CE_URL_S->content_type, IMAGE_JPG);
- break;
- case IL_PNG:
- StrAllocCopy(CE_URL_S->content_type, IMAGE_PNG);
- break;
-
- case IL_PPM:
- StrAllocCopy(CE_URL_S->content_type, IMAGE_PPM);
- break;
- default:
- assert(0); /* should NEVER get this!! */
- break;
- }
-
- }
- else
- #endif /* MOZILLA_CLIENT */
- {
- #if defined(XP_MAC)
- char * macType, *macEncoding;
- Bool useDefault;
-
- FE_FileType(CE_URL_S->address, &useDefault, &macType, &macEncoding);
- if (useDefault)
- {
- #endif
- NET_cinfo * type = NET_cinfo_find_type(CE_URL_S->address);
- NET_cinfo * enc = NET_cinfo_find_enc(CE_URL_S->address);
-
- #if defined(XP_MAC)
- if (macType)
- XP_FREE(macType);
- #endif
-
- StrAllocCopy(CE_URL_S->content_type, type->type);
- StrAllocCopy(CE_URL_S->content_encoding, enc->encoding);
-
-
- if(type->is_default && NET_ContainsHTML(NET_Socket_Buffer, count))
- StrAllocCopy(CE_URL_S->content_type, TEXT_HTML);
-
- #if defined(XP_MAC)
- }
- else
- {
- CE_URL_S->content_type = macType;
- CE_URL_S->content_encoding = macEncoding;
- }
- #endif
- }
- }
-
- CD_RANGE_LENGTH = 0;
- CE_BYTES_RECEIVED = 0;
-
- /* check to see if we need to do a byterange here
- * If we are then set the ranges in the URL
- * so that the streams know the byte range.
- * Once we parse one byterange copy
- */
- if(CD_BYTERANGE_STRING && *CD_BYTERANGE_STRING)
- {
- int32 low=0, high=0;
- char *cp, *dash;
-
- cp = XP_STRCHR(CD_BYTERANGE_STRING, ',');
- if(cp)
- *cp = '\0';
-
- dash = XP_STRCHR(CD_BYTERANGE_STRING, '-');
-
- if(!dash)
- {
- /* no dash is an invalid byte range
- * return zero and we will come back
- * in here and give the whole file or
- * the next byterange
- */
- return(0);
- }
- else
- {
- *dash = '\0';
-
- if(CD_BYTERANGE_STRING == dash)
- low = -1;
- else
- low = atol(CD_BYTERANGE_STRING);
- high = atol(dash+1);
- }
-
-
- if(low < 0 && high < 1)
- {
- /* if both low and high are non-positive
- * it's an error
- */
- return(0);
- }
- else if(low < 0)
- {
- /* This is a byte range that specifies
- * the last bytes of a file. For
- * instance http://host/dir/foo;byterange=-500
- */
- low = CE_URL_S->content_length-(atoi(CD_BYTERANGE_STRING+1));
- high = CE_URL_S->content_length;
- }
- else if(high < 1)
- {
- /* This is a byte range that specifies
- * the a byte range from a specified point
- * till the end of the file. For
- * instance http://host/dir/foo;byterange=500-
- */
- high = CE_URL_S->content_length;
- }
-
- if(low >= CE_URL_S->content_length)
- {
- /* error to have the low byte range be larger than
- * the file
- */
- return(0);
- }
- else if(high >= CE_URL_S->content_length)
- {
- high = CE_URL_S->content_length;
- }
-
- CE_URL_S->low_range = low;
- CE_URL_S->high_range = high;
-
- CD_RANGE_LENGTH = (high-low)+1;
-
- if(cp)
- XP_MEMCPY(CD_BYTERANGE_STRING, cp+1, XP_STRLEN(cp+1)+1);
- else
- CD_BYTERANGE_STRING = 0;
- }
-
- if (CLEAR_CACHE_BIT(CE_FORMAT_OUT) == FO_PRESENT)
- {
- if (NET_URL_Type(CE_URL_S->address) == NEWS_TYPE_URL)
- {
- #ifdef MOZILLA_CLIENT
- #ifdef MOZ_MAIL_NEWS
- /* #### DISGUSTING KLUDGE to make cacheing work for news articles. */
- CE_STATUS = net_InitializeNewsFeData (cur_entry);
- if (CE_STATUS < 0)
- {
- /* #### what error message? */
- return CE_STATUS;
- }
- #endif /* MOZ_MAIL_NEWS */
- #else
- XP_ASSERT(0);
- #endif /* MOZILLA_CLIENT */
- }
- else if (!XP_STRNCMP(CE_URL_S->address, "Mailbox://", 10))
- {
- #ifdef MOZILLA_CLIENT
- #ifdef MOZ_MAIL_NEWS
- /* #### DISGUSTING KLUDGE to make cacheing work for imap articles. */
- CE_STATUS = IMAP_InitializeImapFeData (cur_entry);
- if (CE_STATUS < 0)
- {
- /* #### what error message? */
- return CE_STATUS;
- }
- #endif /* MOZ_MAIL_NEWS */
- #else
- XP_ASSERT(0);
- #endif /* MOZILLA_CLIENT */
- }
- }
-
- CD_STREAM = NET_StreamBuilder(CE_FORMAT_OUT, CE_URL_S, CE_WINDOW_ID);
-
- if(!CD_STREAM)
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_CONVERT);
- return(MK_UNABLE_TO_CONVERT);
- }
-
- #ifdef MOZILLA_CLIENT
- GH_UpdateGlobalHistory(CE_URL_S);
- #endif /* MOZILLA_CLIENT */
-
- /* seek back to the beginning so that
- * we are not forced to write out this
- * first block without calling is_write_ready
- *
- * this also seeks to the beginning of the range that we
- * are going to send
- */
- XP_FileSeek(CD_FILE_PTR, CE_URL_S->low_range, SEEK_SET);
-
- CD_NEXT_STATE = NET_READ_FILE_CHUNK;
- CD_PAUSE_FOR_READ = TRUE;
-
- return(CE_STATUS); /* ok */
- }
-
- PRIVATE int
- net_open_directory (ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
-
- TRACEMSG(("Trying to open directory: %s", CD_FILENAME));
-
- if((CD_DIR_PTR = XP_OpenDir (CD_FILENAME, xpURL)) != NULL)
- {
- CD_NEXT_STATE = NET_READ_DIRECTORY_CHUNK;
- }
- else
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_OPEN_FILE,
- CD_FILENAME);
- return(MK_UNABLE_TO_OPEN_FILE);
- }
-
- CD_IS_DIR = TRUE;
-
- FE_GraphProgressInit(CE_WINDOW_ID, CE_URL_S, CE_URL_S->content_length);
- CD_DESTROY_GRAPH_PROGRESS = TRUE; /* we will need to destroy it */
- CD_ORIGINAL_CONTENT_LENGTH = CE_URL_S->content_length;
- NET_Progress(CE_WINDOW_ID, XP_GetString(XP_PROGRESS_READDIR));
-
- /* make sure the last character isn't a slash
- */
- if(CD_FILENAME[XP_STRLEN(CD_FILENAME)-1] == '/')
- CD_FILENAME[XP_STRLEN(CD_FILENAME)-1] = '\0';
-
- return(0); /* ok */
- }
-
- /* read part of a file and push it out the stream
- */
- PRIVATE int
- net_read_file_chunk(ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
- int count;
- int32 read_size = IS_WRITE_READY;
-
- /* If the stream sink doesn't want any data yet, do nothing. */
- if (read_size == 0)
- {
- CD_PAUSE_FOR_READ = TRUE;
- return NET_READ_FILE_CHUNK;
- }
-
- read_size = MIN(read_size, NET_Socket_Buffer_Size);
-
- if(CD_RANGE_LENGTH)
- read_size = MIN(read_size, CD_RANGE_LENGTH-CE_BYTES_RECEIVED);
-
- count = XP_FileRead(NET_Socket_Buffer, read_size, CD_FILE_PTR);
-
- if(count < 1 || (CD_RANGE_LENGTH && CE_BYTES_RECEIVED >= CD_RANGE_LENGTH))
- {
- if(CE_URL_S->real_content_length > CE_URL_S->content_length)
- {
- /* this is a case of a partial cache file.
- * we need to fall out of here and
- * get the rest of the file from the
- * network
- */
- cur_entry->save_stream = CD_STREAM;
- CD_STREAM = NULL;
- NET_ClearFileReadSelect(CE_WINDOW_ID, XP_Fileno(CD_FILE_PTR));
- if (!CE_URL_S->load_background)
- NET_Progress(CE_WINDOW_ID, XP_GetString(XP_PROGRESS_FILEDONE));
- XP_FileClose(CD_FILE_PTR);
- CE_SOCK = NULL;
- CD_FILE_PTR = 0;
- CD_NEXT_STATE = NET_FILE_FREE;
- return(MK_GET_REST_OF_PARTIAL_FILE_FROM_NETWORK);
- }
- else if(CD_BYTERANGE_STRING && *CD_BYTERANGE_STRING)
- {
- /* go get more byte ranges */
- COMPLETE_STREAM;
- CD_NEXT_STATE = NET_SETUP_FILE_STREAM;
- if (!CE_URL_S->load_background)
- NET_Progress(CE_WINDOW_ID, XP_GetString( XP_READING_SEGMENT ) );
- return(0);
- }
-
- NET_ClearFileReadSelect(CE_WINDOW_ID, XP_Fileno(CD_FILE_PTR));
- if (!CE_URL_S->load_background)
- NET_Progress(CE_WINDOW_ID, XP_GetString(XP_PROGRESS_FILEDONE));
- XP_FileClose(CD_FILE_PTR);
- CE_SOCK = NULL;
- CD_FILE_PTR = 0;
- CD_NEXT_STATE = NET_FILE_DONE;
- return(MK_DATA_LOADED);
- }
-
- CE_BYTES_RECEIVED += count;
-
- CE_STATUS = PUTB(NET_Socket_Buffer, count);
-
- if (!CE_URL_S->load_background)
- FE_GraphProgress(CE_WINDOW_ID, CE_URL_S, CE_BYTES_RECEIVED, count,
- CE_URL_S->content_length);
-
- CD_PAUSE_FOR_READ = TRUE;
-
- return(CE_STATUS);
- }
-
- PRIVATE int
- net_read_directory_chunk (ActiveEntry * cur_entry)
- {
-
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
- NET_FileEntryInfo * file_entry;
- XP_DirEntryStruct * dir_entry;
- XP_StatStruct stat_entry;
- char *full_path=0;
- int32 len;
-
- CD_SORT_BASE = NET_SortInit();
-
- while((dir_entry = XP_ReadDir(CD_DIR_PTR)) != 0)
- {
-
- /* skip . and ..
- */
- if(!XP_STRCMP(dir_entry->d_name, "..") || !XP_STRCMP(dir_entry->d_name, "."))
- continue;
-
- file_entry = NET_CreateFileEntryInfoStruct();
- if(!file_entry)
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_OUT_OF_MEMORY);
- return(MK_OUT_OF_MEMORY);
- }
-
- /* escape and copy
- */
- file_entry->filename = NET_Escape(dir_entry->d_name, URL_PATH);
-
- /* make a full path */
- len = XP_STRLEN(CD_FILENAME) + XP_STRLEN(dir_entry->d_name) + 30;
- FREEIF(full_path);
- full_path = (char *)XP_ALLOC(len*sizeof(char));
-
- if(!full_path)
- return(MK_OUT_OF_MEMORY);
-
- XP_STRCPY(full_path, CD_FILENAME);
- XP_STRCAT(full_path, "/");
- XP_STRCAT(full_path, dir_entry->d_name);
-
- if(XP_Stat(full_path, &stat_entry, xpURL) != -1)
- {
- TRACEMSG(("Found stat info for file %s\n",full_path));
-
- if(S_ISDIR(stat_entry.st_mode))
- {
- file_entry->special_type = NET_DIRECTORY;
- StrAllocCat(file_entry->filename, "/");
- }
- else
- {
- file_entry->cinfo = NET_cinfo_find_type(file_entry->filename);
- }
-
- file_entry->size = (int32) stat_entry.st_size;
- file_entry->date = stat_entry.st_mtime;
-
- TRACEMSG(("Got file: %s, %ld",file_entry->filename, file_entry->size));
-
- NET_SortAdd(CD_SORT_BASE, file_entry);
- }
- }
-
- FREEIF(full_path);
-
- NET_Progress(CE_WINDOW_ID, XP_GetString(XP_PROGRESS_DIRDONE));
-
- XP_CloseDir(CD_DIR_PTR);
- CD_DIR_PTR = 0;
-
- CD_NEXT_STATE = NET_BEGIN_PRINT_DIRECTORY;
-
- return(0);
- }
-
- /* emit application/http-index-format */
- PRIVATE int
- net_BeginPrintDirectory(ActiveEntry * ce)
- {
- FILEConData * cd = (FILEConData *) ce->con_data;
-
- cd->next_state = NET_PRINT_DIRECTORY;
-
- return(ce->status);
- }
-
-
- #define PD_PUTS(s) \
- do { \
- if(status > -1) \
- status = (*stream->put_block)(stream, s, XP_STRLEN(s)); \
- } while(0)
-
- PUBLIC int
- NET_PrintDirectory(SortStruct **sort_base, NET_StreamClass * stream, char * path, URL_Struct *URL_s)
- {
- NET_FileEntryInfo * file_entry;
- char out_buf[3096];
- char *esc_path = NET_Escape(path, URL_PATH);
- int i;
- int status=0;
-
- NET_DoFileSort(*sort_base);
-
- /* emit 300: URL CRLF */
- XP_STRCPY(out_buf, "300: ");
- PD_PUTS(out_buf);
- PR_snprintf(out_buf, sizeof(out_buf), URL_s->address);
- PD_PUTS(out_buf);
-
- XP_STRCPY(out_buf, CRLF);
- PD_PUTS(out_buf);
-
- /* emit 200: Filename Size Content-Type File-type Last-Modified */
- XP_STRCPY(out_buf, "200: Filename Content-Length Content-Type File-type Last-Modified"CRLF);
- PD_PUTS(out_buf);
-
- for(i=0; status > -1 && (file_entry = (NET_FileEntryInfo *)
- NET_SortRetrieveNumber(*sort_base, i)) != 0;
- i++)
- {
-
-
- char * esc_time = NET_Escape(ctime(&file_entry->date), URL_XALPHAS);
-
- XP_STRTOK(file_entry->filename, "/");
- PR_snprintf(out_buf, sizeof(out_buf), "201: %s %ld %s %s %s"CRLF,
- file_entry->filename,
- file_entry->size,
- file_entry->special_type == NET_DIRECTORY ? "application/http-index-format" :
- file_entry->cinfo ? file_entry->cinfo->type : TEXT_PLAIN,
- file_entry->special_type == NET_DIRECTORY ? "Directory" : "File",
- esc_time);
-
- FREE(esc_time);
-
- PD_PUTS(out_buf);
-
- NET_FreeEntryInfoStruct(file_entry);
- }
-
- NET_SortFree(*sort_base);
- *sort_base = 0;
-
- FREEIF(esc_path);
- if(status < 0)
- return(status);
- return(MK_DATA_LOADED);
- }
-
- /* if the url is a local file this function returns
- * the portion of the url that represents the
- * file path as a malloc'd string. If the
- * url is not a local file url this function
- * returns NULL
- */
- PRIVATE char *
- net_return_local_file_part_from_url(char *address)
- {
- char *host;
- #ifdef XP_WIN
- char *new_address;
- char *rv;
- #endif
-
- if (address == NULL)
- return NULL;
-
- /* imap urls are never local */
- if (!strncasecomp(address,"mailbox://",10))
- return NULL;
-
- /* mailbox url's are always local, but don't always point to a file */
- if(!strncasecomp(address, "mailbox:", 8))
- {
- char *filename = NET_ParseURL(address, GET_PATH_PART);
- if (!filename)
- filename = XP_STRDUP("");
- return filename;
- }
-
- if(strncasecomp(address, "file:", 5))
- return(NULL);
-
- host = NET_ParseURL(address, GET_HOST_PART);
-
- if(!host || *host == '\0' || !strcasecomp(host, "LOCALHOST"))
- {
- FREEIF(host);
- return(NET_UnEscape(NET_ParseURL(address, GET_PATH_PART)));
- }
-
- #ifdef XP_WIN
- /* get the address minus the search and hash data */
- new_address = NET_ParseURL(address,
- GET_PROTOCOL_PART | GET_HOST_PART | GET_PATH_PART);
- NET_UnEscape(new_address);
-
- /* check for local drives as hostnames
- */
- if(XP_STRLEN(host) == 2
- && isalpha(host[0])
- && (host[1] == '|' || host[1] == ':'))
- {
- FREE(host);
- /* skip "file:/" */
- rv = XP_STRDUP(new_address+6);
- FREE(new_address);
- return(rv);
- }
-
- if(1)
- {
- XP_StatStruct stat_entry;
- /* try stating the url just in case since
- * the local file system can
- * have url's of the form \\prydain\dist
- */
- if(-1 != XP_Stat(address+5, &stat_entry, xpURL))
- {
- FREE(host);
- /* skip "file:" */
- rv = XP_STRDUP(address+5);
- FREE(new_address);
- return(rv);
- }
- }
- #endif /* XP_WIN */
-
- FREE(host);
-
- return(NULL);
- }
-
- /* returns TRUE if the url is a local file
- * url
- */
- PUBLIC XP_Bool
- NET_IsLocalFileURL(char *address)
- {
- char * cp = net_return_local_file_part_from_url(address);
-
- if(cp)
- {
- FREE(cp);
- return(TRUE);
- }
- else
- {
- return(FALSE);
- }
- }
-
- /* load local files and
- * display directories
- *
- * if cache_file is not null then we this module is being used to
- * read a localy cached url. Use the passed in cache_file variable
- * as the location of the file and use the URL->address as the
- * URL for StreamBuilding etc.
- */
- PRIVATE int32
- net_FileLoad (ActiveEntry * cur_entry)
- {
- char * cp;
- FILEConData * connection_data;
-
- #ifndef NSPR20_DISABLED
- NET_SetCallNetlibAllTheTime(CE_WINDOW_ID, "mkfile");
- #endif /* NSPR20_DISABLED */
-
- /* make space for the connection data */
- cur_entry->con_data = XP_NEW(FILEConData);
- if(!cur_entry->con_data)
- {
- FE_Alert(CE_WINDOW_ID, XP_GetString(XP_ALERT_OUTMEMORY));
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_OUT_OF_MEMORY);
- CE_STATUS = MK_OUT_OF_MEMORY;
- return(CE_STATUS);
- }
-
- /* zero out the structure
- */
- XP_MEMSET(cur_entry->con_data, 0, sizeof(FILEConData));
-
- /* set this to make the CD_ macros work */
- connection_data = cur_entry->con_data;
-
- if(!CE_URL_S->cache_file)
- {
- char *path;
-
- if(!(path = net_return_local_file_part_from_url(CE_URL_S->address)))
- {
- FREE(cur_entry->con_data);
- cur_entry->con_data = 0;
- return(MK_USE_FTP_INSTEAD); /* use ftp */
- }
-
- CD_FILENAME = path;
- }
- else
- {
- StrAllocCopy(CD_FILENAME, CE_URL_S->cache_file);
- CD_IS_CACHE_FILE = TRUE;
- }
-
- TRACEMSG(("Load File: looking for file: %s\n",CD_FILENAME));
-
- /* don't cache local files or local directory listings
- * if we are only looking to cache this file fail now
- */
- if(cur_entry->format_out == FO_CACHE_ONLY)
- return -1;
- cur_entry->format_out = CLEAR_CACHE_BIT(cur_entry->format_out);
-
- /* all non-cache filenames must begin with slash
- */
- if(!CD_IS_CACHE_FILE == TRUE && *CD_FILENAME != '/')
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(
- MK_UNABLE_TO_LOCATE_FILE,
- *CD_FILENAME ? CD_FILENAME : "/");
- CE_STATUS = MK_UNABLE_TO_LOCATE_FILE;
- return(MK_UNABLE_TO_LOCATE_FILE);
- }
-
- #define BYTERANGE_TOKEN "bytes="
-
- #ifdef URL_BYTERANGE_METHOD
- /* if the URL has ";bytes=" in it then it
- * is a special partial byterange url.
- * Parse out the byterange part and store it
- * away
- */
- #define URL_BYTERANGE_TOKEN ";"BYTERANGE_TOKEN
- if (CD_IS_CACHE_FILE && (cp = strcasestr(CE_URL_S->address, URL_BYTERANGE_TOKEN)) != NULL)
- {
- StrAllocCopy(CD_BYTERANGE_STRING, cp+XP_STRLEN(URL_BYTERANGE_TOKEN));
- XP_STRTOK(CD_BYTERANGE_STRING, ";");
- }
- else if ((cp = strcasestr(CD_FILENAME, URL_BYTERANGE_TOKEN)) != NULL)
- {
- *cp = '\0';
- /* remove any other weird ; stuff */
- XP_STRTOK(cp+1, ";");
- StrAllocCopy(CD_BYTERANGE_STRING, cp+XP_STRLEN(URL_BYTERANGE_TOKEN));
- }
- #endif /* URL_BYTERANGE_METHOD */
-
- /* this is the byterange header method.
- * both the URL byterange and the header
- * byterange methods can coexist peacefully
- */
- if(CE_URL_S->range_header && !XP_STRNCMP(CE_URL_S->range_header, BYTERANGE_TOKEN, XP_STRLEN(BYTERANGE_TOKEN)))
- {
- StrAllocCopy(CD_BYTERANGE_STRING, CE_URL_S->range_header+XP_STRLEN(BYTERANGE_TOKEN));
- }
-
- /* lets do a local file read
- */
- cur_entry->local_file = TRUE; /* se we don't select on the socket id */
-
- CD_NEXT_STATE = NET_CHECK_FILE_TYPE;
-
- return(net_ProcessFile(cur_entry));
- }
-
- PRIVATE int32
- net_ProcessFile (ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *) cur_entry->con_data;
-
- TRACEMSG(("Entering ProcessFile with state #%d\n",CD_NEXT_STATE));
-
- CD_PAUSE_FOR_READ = FALSE;
-
- while(!CD_PAUSE_FOR_READ)
- {
-
- switch (CD_NEXT_STATE)
- {
- case NET_CHECK_FILE_TYPE:
- CE_STATUS = net_check_file_type(cur_entry);
- break;
-
- case NET_DELETE_FILE:
- CE_STATUS = net_delete_file(cur_entry);
- break;
-
- case NET_PUT_FILE:
- CE_STATUS = net_put_file(cur_entry);
- break;
-
- case NET_MOVE_FILE:
- CE_STATUS = net_move_file(cur_entry);
- break;
-
- case NET_MAKE_DIRECTORY:
- CE_STATUS = net_make_directory(cur_entry);
- break;
-
- case NET_FILE_SETUP_STREAM:
- CE_STATUS = net_file_setup_stream(cur_entry);
- break;
-
- case NET_OPEN_FILE:
- CE_STATUS = net_open_file(cur_entry);
- break;
-
- case NET_SETUP_FILE_STREAM:
- CE_STATUS = net_setup_file_stream(cur_entry);
- break;
-
- case NET_OPEN_DIRECTORY:
- CE_STATUS = net_open_directory(cur_entry);
- break;
-
- case NET_READ_FILE_CHUNK:
- CE_STATUS = net_read_file_chunk(cur_entry);
- break;
-
- case NET_READ_DIRECTORY_CHUNK:
- CE_STATUS = net_read_directory_chunk(cur_entry);
- break;
-
- case NET_BEGIN_PRINT_DIRECTORY:
- CE_STATUS = net_BeginPrintDirectory(cur_entry);
- break;
-
- case NET_PRINT_DIRECTORY:
- if((*CD_STREAM->is_write_ready)(CD_STREAM))
- {
- CE_STATUS = NET_PrintDirectory(&CD_SORT_BASE, CD_STREAM, CD_FILENAME, CE_URL_S);
- CD_NEXT_STATE = NET_FILE_DONE;
- }
- else
- {
- /* come back into this state */
- if(!connection_data->calling_netlib_all_the_time)
- {
- connection_data->calling_netlib_all_the_time = TRUE;
- NET_SetCallNetlibAllTheTime(CE_WINDOW_ID, "mkfile");
- }
- cur_entry->memory_file = TRUE;
- cur_entry->socket = NULL;
- CD_PAUSE_FOR_READ = TRUE;
- }
- break;
-
- case NET_FILE_DONE:
- if(CD_STREAM)
- COMPLETE_STREAM;
- CD_NEXT_STATE = NET_FILE_FREE;
- break;
-
- case NET_FILE_ERROR_DONE:
- if(CD_STREAM)
- ABORT_STREAM(CE_STATUS);
- if(CD_DIR_PTR)
- XP_CloseDir(CD_DIR_PTR);
- if(CD_FILE_PTR)
- {
- CE_SOCK = NULL;
- NET_ClearFileReadSelect(CE_WINDOW_ID, XP_Fileno(CD_FILE_PTR));
- XP_FileClose(CD_FILE_PTR);
- }
- CD_NEXT_STATE = NET_FILE_FREE;
- break;
-
- case NET_FILE_FREE:
- if(connection_data->calling_netlib_all_the_time)
- {
- NET_ClearCallNetlibAllTheTime(CE_WINDOW_ID, "mkfile");
- connection_data->calling_netlib_all_the_time = FALSE;
- }
-
- if(CD_DESTROY_GRAPH_PROGRESS)
- FE_GraphProgressDestroy(CE_WINDOW_ID,
- CE_URL_S,
- CD_ORIGINAL_CONTENT_LENGTH,
- CE_BYTES_RECEIVED);
- FREE(CD_FILENAME);
- FREEIF(CD_STREAM);
- FREE(cur_entry->con_data);
-
- #ifndef NSPR20_DISABLED
- NET_ClearCallNetlibAllTheTime(CE_WINDOW_ID, "mkfile");
- #endif /* NSPR20_DISABLED */
-
- return(-1); /* done */
- }
-
- if(CE_STATUS < 0 && CD_NEXT_STATE != NET_FILE_FREE)
- {
- CD_PAUSE_FOR_READ = FALSE;
- CD_NEXT_STATE = NET_FILE_ERROR_DONE;
- }
-
- }
-
- return(0); /* keep going */
- }
-
- PRIVATE int32
- net_InterruptFile(ActiveEntry * cur_entry)
- {
- FILEConData * connection_data = (FILEConData *)cur_entry->con_data;
-
- CD_NEXT_STATE = NET_FILE_ERROR_DONE;
- CE_STATUS = MK_INTERRUPTED;
-
- return(net_ProcessFile(cur_entry));
- }
-
- PRIVATE void
- net_CleanupFile(void)
- {
- return;
- }
-
- typedef struct {
- HTTPIndexParserData *parse_data;
- MWContext *context;
- int format_out;
- URL_Struct *URL_s;
- } index_format_conv_data_object;
-
- PRIVATE int net_IdxConvPut(NET_StreamClass *stream, char *s, int32 l)
- {
- index_format_conv_data_object *obj=stream->data_object;
- return(NET_HTTPIndexParserPut(obj->parse_data, s, l));
- }
-
- PRIVATE int net_IdxConvWriteReady(NET_StreamClass *stream)
- {
- return(MAX_WRITE_READY);
- }
-
- /* take the parsed data and generate HTML */
- PRIVATE void net_IdxConvComplete(NET_StreamClass *inputStream)
- {
- index_format_conv_data_object *obj=inputStream->data_object;
- int32 num_files = NET_HTTPIndexParserGetTotalFiles(obj->parse_data);
- NET_FileEntryInfo * file_entry;
- int32 max_name_length, i, status = 0, window_width, len;
- char out_buf[3096], *name, *date, *ptr;
- NET_StreamClass *stream;
- NET_cinfo * cinfo;
- char *base_url=NULL, *path=NULL;
-
- /* direct the stream to the html parser */
- StrAllocCopy(obj->URL_s->content_type, TEXT_HTML);
-
- stream = NET_StreamBuilder(obj->format_out,
- obj->URL_s,
- obj->context);
- if(!stream)
- goto cleanup;
-
- /* Ask layout how wide the window is in the <PRE> font, to decide
- how much space we should allocate for the file name column. */
- # define LISTING_OVERHEAD 51
- #ifdef MOZILLA_CLIENT
- window_width = LO_WindowWidthInFixedChars (obj->context);
- #else
- window_width = 80;
- #endif /* MOZILLA_CLIENT */
-
- max_name_length = (window_width - LISTING_OVERHEAD);
- if (max_name_length < 12) /* 8.3 */
- max_name_length = 12;
- else if (max_name_length > 50)
- max_name_length = 50;
-
- /* the the base url and path */
- if((base_url = NET_HTTPIndexParserGetBaseURL(obj->parse_data)) != NULL)
- {
- path = NET_ParseURL(base_url, GET_PATH_PART);
-
- if (path && path != '\0') /* Not Empty path: */
- {
- int end;
- NET_UnEscape(path);
-
- end = XP_STRLEN(path)-1;
- /* if the path ends with a slash kill it.
- * that includes the path "/"
- */
- if(path[end] == '/')
- {
- path[end] = 0; /* kill the last slash */
- }
-
- /* output "directory of ..." message */
- PR_snprintf(out_buf, sizeof(out_buf),
- XP_GetString( XP_TITLE_DIRECTORY_OF_ETC ),
- *path ? path : "/", *path ? path : "/");
- PD_PUTS(out_buf);
- }
- }
-
- if(NET_HTTPIndexParserGetHTMLMessage(obj->parse_data))
- {
- XP_STRCPY(out_buf, CRLF"<HR>"CRLF);
- PD_PUTS(out_buf);
-
- PD_PUTS(NET_HTTPIndexParserGetHTMLMessage(obj->parse_data));
-
- if(!NET_HTTPIndexParserGetTextMessage(obj->parse_data))
- {
- XP_STRCPY(out_buf, CRLF"<HR>"CRLF);
- PD_PUTS(out_buf);
- }
- }
-
- PR_snprintf(out_buf, sizeof(out_buf), "<PRE>"CRLF);
- PD_PUTS(out_buf); /* output the line */
-
- if(NET_HTTPIndexParserGetTextMessage(obj->parse_data))
- {
- char *msg;
-
- XP_STRCPY(out_buf, "<HR>");
- PD_PUTS(out_buf);
-
- msg = NET_HTTPIndexParserGetTextMessage(obj->parse_data);
-
- status = NET_ScanForURLs (NULL, msg,
- XP_STRLEN(msg),
- out_buf, sizeof(out_buf),
- TRUE);
- PD_PUTS(out_buf);
-
- XP_STRCPY(out_buf, "<HR>");
- PD_PUTS(out_buf);
- }
-
- /* allow the user to go up if path is not empty
- */
- if(path && *path != '\0')
- {
- char *cp = XP_STRRCHR(path, '/');
- XP_STRCPY(out_buf, "<A HREF=\"");
- PD_PUTS(out_buf);
- if(cp)
- {
- *cp = '\0';
- PD_PUTS(path);
- *cp = '/';
- XP_STRCPY(out_buf, "/");
- PD_PUTS(out_buf);
- }
- XP_STRNCPY_SAFE(out_buf,
- XP_GetString(XP_UPTO_HIGHER_LEVEL_DIRECTORY),
- sizeof(out_buf));
- PD_PUTS(out_buf);
- }
-
- for(i=0; i < num_files; i++)
- {
-
- file_entry = NET_HTTPIndexParserGetFileNum(obj->parse_data, i);
-
- if(!file_entry)
- continue;
-
- if(!file_entry->date)
- {
- PR_snprintf(out_buf, sizeof(out_buf), " <A HREF=\"%s\">",
- file_entry->filename);
- PD_PUTS(out_buf); /* output the line */
-
- PR_snprintf(out_buf, sizeof(out_buf), "%s</A>\n",
- NET_UnEscape(file_entry->filename));
- PD_PUTS(out_buf); /* output the line */
- }
- else
- {
- int max_size_for_this_name;
-
- date = ctime(&file_entry->date);
- if(date)
- date[24] = '\0'; /* strip return */
- else
- date = "";
-
- PR_snprintf(out_buf, sizeof(out_buf), " <A HREF=\"%s\">",
- file_entry->filename);
- PD_PUTS(out_buf); /* output the line */
-
- /* do content_type icon stuff here */
- cinfo = NET_cinfo_find_info_by_type(file_entry->content_type);
-
- if(file_entry->special_type == NET_DIRECTORY
- || file_entry->special_type == NET_SYM_LINK
- || file_entry->special_type == NET_SYM_LINK_TO_DIR
- || file_entry->special_type == NET_SYM_LINK_TO_FILE)
- {
- PR_snprintf(out_buf,
- sizeof(out_buf),
- "<IMG ALIGN=absbottom "
- "BORDER=0 SRC=\"internal-gopher-menu\">");
- }
- else if(cinfo && cinfo->icon)
- {
- PR_snprintf(out_buf, sizeof(out_buf),
- "<IMG ALIGN=absbottom BORDER=0 SRC=\"%.512s\">",
- cinfo->icon);
- }
- else
- {
- PR_snprintf(out_buf,
- sizeof(out_buf),
- "<IMG ALIGN=absbottom BORDER=0 "
- "SRC=\"internal-gopher-unknown\">");
- }
-
- PD_PUTS(out_buf); /* output the line */
-
- #define SIZE_LISTING_OVERHEAD 9
-
- /* print the filename
- */
- name = NET_UnEscape (file_entry->filename);
- len = XP_STRLEN (name);
- max_size_for_this_name = max_name_length;
- if(!file_entry->size)
- max_size_for_this_name += SIZE_LISTING_OVERHEAD;
-
- if(len > max_size_for_this_name)
- {
- XP_STRCPY (out_buf, " ");
- XP_MEMCPY (out_buf + 1, name, max_name_length - 3);
- XP_STRCPY (out_buf + 1 + max_name_length - 3, "...</A>");
- }
- else
- {
- XP_STRCPY (out_buf, " ");
- XP_STRCAT (out_buf, name);
- XP_STRCAT (out_buf, "</A>");
- }
- PD_PUTS(out_buf); /* output the line */
-
- /* put a standard number of spaces between the name and date
- */
- for(ptr = out_buf; len < max_size_for_this_name; len++)
- {
- *ptr++ = ' ';
- }
- *ptr = '\0';
-
- /* start from the end of out_buf
- *
- * note: add 4 to the date to get rid of the day of the week
- */
- if(file_entry->size)
- {
- PR_snprintf(&out_buf[XP_STRLEN(out_buf)],
- sizeof(out_buf) - XP_STRLEN(out_buf),
- " %5ld %s %s ",
- file_entry->size > 1024 ?
- file_entry->size/1024 : file_entry->size,
- file_entry->size > 1024 ? "Kb" : " b",
- date+4);
- }
- else
- {
- PR_snprintf(&out_buf[XP_STRLEN(out_buf)],
- sizeof(out_buf) - XP_STRLEN(out_buf),
- " %s ", date+4);
- }
-
- PD_PUTS(out_buf); /* output the line */
-
- if(file_entry->special_type == NET_SYM_LINK
- || file_entry->special_type == NET_SYM_LINK_TO_DIR
- || file_entry->special_type == NET_SYM_LINK_TO_FILE)
- {
- PR_snprintf(out_buf, sizeof(out_buf), "Symbolic link\n");
- }
- else if(file_entry->special_type == NET_DIRECTORY)
- {
- PR_snprintf(out_buf, sizeof(out_buf), "Directory\n");
- }
- else if(cinfo && cinfo->desc)
- {
- PR_snprintf(out_buf,
- sizeof(out_buf)-1,
- "%s",
- cinfo->desc);
- XP_STRCAT(out_buf, "\n");
- }
- else
- {
- XP_STRCPY(out_buf, "\n");
- }
-
- PD_PUTS(out_buf);
- }
- }
-
- XP_STRCPY(out_buf, "\n</PRE>");
- PD_PUTS(out_buf);
-
- cleanup:
- NET_HTTPIndexParserFree(obj->parse_data);
- FREEIF(path);
- }
-
- PRIVATE void net_IdxConvAbort(NET_StreamClass *stream, int32 status)
- {
- index_format_conv_data_object *obj=stream->data_object;
- NET_HTTPIndexParserFree(obj->parse_data);
- }
-
- PUBLIC NET_StreamClass *
- NET_HTTPIndexFormatToHTMLConverter(int format_out,
- void *data_object,
- URL_Struct *URL_s,
- MWContext *window_id)
- {
- index_format_conv_data_object* obj;
- NET_StreamClass* stream;
-
- TRACEMSG(("Setting up display stream. Have URL: %s\n", URL_s->address));
-
- stream = XP_NEW(NET_StreamClass);
- if(stream == NULL)
- return(NULL);
-
- obj = XP_NEW(index_format_conv_data_object);
- if (obj == NULL)
- {
- FREE(stream);
- return(NULL);
- }
-
- XP_MEMSET(obj, 0, sizeof(index_format_conv_data_object));
-
- obj->parse_data = NET_HTTPIndexParserInit();
-
- if(!obj->parse_data)
- {
- FREE(stream);
- FREE(obj);
- }
-
- obj->context = window_id;
- obj->URL_s = URL_s;
- obj->format_out = format_out;
-
- stream->name = "HTTP index format converter";
- stream->complete = (MKStreamCompleteFunc) net_IdxConvComplete;
- stream->abort = (MKStreamAbortFunc) net_IdxConvAbort;
- stream->put_block = (MKStreamWriteFunc) net_IdxConvPut;
- stream->is_write_ready = (MKStreamWriteReadyFunc) net_IdxConvWriteReady;
- stream->data_object = obj; /* document info object */
- stream->window_id = window_id;
-
- return(stream);
- }
-
- #include "libmocha.h"
-
- #define SANE_BUFLEN 1024
-
- NET_StreamClass *
- net_CloneWysiwygLocalFile(MWContext *window_id, URL_Struct *URL_s,
- uint32 nbytes, const char * wysiwyg_url,
- const char * base_href)
- {
- char *filename;
- XP_File fromfp;
- NET_StreamClass *stream;
- int32 buflen, len;
- char *buf;
-
- filename = net_return_local_file_part_from_url(URL_s->address);
- if (!filename)
- return NULL;
- fromfp = XP_FileOpen(filename, xpURL, XP_FILE_READ_BIN);
- FREE(filename);
- if (!fromfp)
- return NULL;
- stream = LM_WysiwygCacheConverter(window_id, URL_s, wysiwyg_url,
- base_href);
- if (!stream)
- {
- XP_FileClose(fromfp);
- return 0;
- }
- buflen = stream->is_write_ready(stream);
- if (buflen > SANE_BUFLEN)
- buflen = SANE_BUFLEN;
- buf = (char *)XP_ALLOC(buflen * sizeof(char));
- if (!buf)
- {
- XP_FileClose(fromfp);
- return 0;
- }
- while (nbytes != 0)
- {
- len = buflen;
- if ((uint32)len > nbytes)
- len = (int32)nbytes;
- len = XP_FileRead(buf, len, fromfp);
- if (len <= 0)
- break;
- if (stream->put_block(stream, buf, len) < 0)
- break;
- nbytes -= len;
- }
- FREE(buf);
- XP_FileClose(fromfp);
- if (nbytes != 0)
- {
- /* NB: Our caller must clear top_state->mocha_write_stream. */
- stream->abort(stream, MK_UNABLE_TO_CONVERT);
- XP_DELETE(stream);
- return 0;
- }
- return stream;
- }
-
- void
- NET_InitFileProtocol(void)
- {
- static NET_ProtoImpl file_proto_impl;
-
- file_proto_impl.init = net_FileLoad;
- file_proto_impl.process = net_ProcessFile;
- file_proto_impl.interrupt = net_InterruptFile;
- file_proto_impl.cleanup = net_CleanupFile;
-
- NET_RegisterProtocolImplementation(&file_proto_impl, FILE_TYPE_URL);
- NET_RegisterProtocolImplementation(&file_proto_impl, FILE_CACHE_TYPE_URL);
- }
-