/* ** Look for cached information for this news server ** We store the information in a URL Tree so that we can have multiple ** servers stored simultanously */ PRIVATE HTNewsCache * HTNewsCache_find (HTRequest * request, const char * url) { HTUTree * tree = NULL; if (request && url) { char * newshost = NULL; HTNewsCache * element = NULL; if (!strncasecomp(url, "news:", 5)) { HTUserProfile * up = HTRequest_userProfile(request); StrAllocCopy(newshost, HTUserProfile_news(up)); } else if (!strncasecomp(url, "nntp:", 5)) { newshost = HTParse(url, "", PARSE_HOST); } /* If we have a news server then continue to find a URL tree */ if (newshost) { char * colon = strchr(newshost, ':'); int port = NEWS_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_find(NEWS_TREE, newshost, port); HT_FREE(newshost); if (!tree) { HTTRACE(PROT_TRACE, "News Cache.. No information for `%s\'\n" _ url); return NULL; } /* Find a cache element (if any) */ element = (HTNewsCache *) HTUTree_findNode(tree, "", "/"); return element; } } return NULL; }
int LYStringToKeycode(char *src) { unsigned n; int key = -1; int len = (int) strlen(src); if (len == 1) { key = *src; } else if (len == 2 && *src == '^') { key = src[1] & 0x1f; } else if (len > 2 && !strncasecomp(src, "0x", 2)) { char *dst = 0; key = (int) strtol(src, &dst, 0); if (non_empty(dst)) key = -1; } else if (len > 6 && !strncasecomp(src, "key-", 4)) { char *dst = 0; key = (int) strtol(src + 4, &dst, 0); if (isEmpty(dst)) key = -1; } if (key < 0) { for (n = 0; n < TABLESIZE(named_keys); n++) { if (!strcasecomp(named_keys[n].name, src)) { key = named_keys[n].key; break; } } } return key; }
// create short icon label from full path/url char *XFE_ComposeAttachFolderView::parseItemLabel(const char *url) { // (alastair) code taken from libmsg/msgsend.cpp - be nice just to call into libmsg // modified slightly to avoid bug of trailing / generating empty name // modified to return truncated label for mail/news URL's if (!url || strlen(url)==0) return XP_STRDUP("(null)"); char *s; char *s2; char *s3; /* If we know the URL doesn't have a sensible file name in it, don't bother emitting a content-disposition. */ if (!strncasecomp (url, "news:", 5)) return XP_STRDUP("news:"); if (!strncasecomp (url, "snews:", 6)) return XP_STRDUP("snews:"); if (!strncasecomp (url, "mailbox:", 8)) return XP_STRDUP("mailbox:"); char *tmpLabel = XP_STRDUP(url); s=tmpLabel; /* remove trailing / or \ */ int len=strlen(s); if (s[len-1]=='/' || s[len-1]=='\\') s[len-1]='\0'; s2 = XP_STRCHR (s, ':'); if (s2) s = s2 + 1; /* Take the part of the file name after the last / or \ */ s2 = XP_STRRCHR (s, '/'); if (s2) s = s2+1; s2 = XP_STRRCHR (s, '\\'); if (s2) s = s2+1; /* if it's a non-file url, strip off any named anchors or search data */ if (XP_STRNCASECMP(url,"file:",5)!=0 && url[0]!='/') { /* Now trim off any named anchors or search data. */ s3 = XP_STRCHR (s, '?'); if (s3) *s3 = 0; s3 = XP_STRCHR (s, '#'); if (s3) *s3 = 0; } /* Now lose the %XX crap. */ NET_UnEscape (s); char *retLabel=XP_STRDUP(s); XP_FREE(tmpLabel); return retLabel; }
PRIVATE BOOL HTNewsCache_update (HTRequest * request, const char * url, HTArray * array) { HTUTree * tree = NULL; if (request && url) { char * newshost = NULL; if (!strncasecomp(url, "news:", 5)) { HTUserProfile * up = HTRequest_userProfile(request); StrAllocCopy(newshost, HTUserProfile_news(up)); } else if (!strncasecomp(url, "nntp:", 5)) { newshost = HTParse(url, "", PARSE_HOST); } /* ** If the news server was found then update the data entry. Otherwise ** create a new entry */ if (newshost) { char * colon = strchr(newshost, ':'); int port = NEWS_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_new(NEWS_TREE, newshost, port, HTNewsCache_delete); HT_FREE(newshost); if (!tree) { HTTRACE(PROT_TRACE, "News Cache.. Can't create tree\n"); return NO; } /* Add new cache information to the tree */ { HTNewsCache * element = NULL; BOOL status; if ((element=(HTNewsCache *) HTUTree_findNode(tree, "", "/"))){ element->cache = array; status = YES; } else { element = HTNewsCache_new(url, array); status = HTUTree_addNode(tree, "", "/", element); } return status; } } } return NO; }
/* * Find the given command-name, accepting an abbreviation if it is unique. */ Kcmd *LYStringToKcmd(const char *name) { size_t need = strlen(name); size_t j; BOOL exact = FALSE; Kcmd *result = 0; Kcmd *maybe = 0; if (non_empty(name)) { for (j = 0; revmap[j].name != 0; j++) { if (!strcasecomp(revmap[j].name, name)) { result = revmap + j; break; } else if (!exact && !strncasecomp(revmap[j].name, name, (int) need)) { if (maybe == 0) { maybe = revmap + j; } else { if (revmap[j].name[need] != 0 && maybe->name[need] != 0) { maybe = 0; exact = TRUE; } } } } } return (result != 0) ? result : maybe; }
/* * Seek and handle a subject=foo. - FM */ PRIVATE void extract_subject ARGS2( char *, dst, char *, src) { CONST char *keyword = "subject="; int len = strlen(keyword); char *cp, *cp1; cp = (src + 1); while (*cp != '\0') { if ((*(cp - 1) == '?' || *(cp - 1) == '&') && !strncasecomp(cp, keyword, len)) break; cp++; } if (*cp) { cp += len; if ((cp1 = strchr(cp, '&')) != NULL) { *cp1 = '\0'; } if (*cp) { strncpy(dst, cp, MAX_SUBJECT); dst[MAX_SUBJECT] = '\0'; SafeHTUnEscape(dst); } if (cp1) { *cp1 = '&'; cp1 = NULL; } } CTRACE((tfp, "extract_subject(%s) = '%s'\n", keyword, NONNULL(dst))); }
PRIVATE void extract_field ARGS3( char **, dst, char *, src, char *, keyword) { int len = strlen(keyword); char *cp, *cp1; cp = (src + 1); while (*cp != '\0') { if ((*(cp - 1) == '?' || *(cp - 1) == '&') && !strncasecomp(cp, keyword, len)) { cp += len; if ((cp1 = strchr(cp, '&')) != NULL) { *cp1 = '\0'; } comma_append(dst, cp); if (cp1) { *cp1 = '&'; cp = cp1; cp1 = NULL; } else { break; } } cp++; } CTRACE((tfp, "extract_field(%s) = '%s'\n", keyword, NONNULL(*dst))); }
BOOLEAN LYgetEnum( Config_Enum *table, char *name, int *result ) { Config_Enum *found = 0; unsigned int len = strlen( name ); int match = 0; if ( len ) { for ( ; table->name[0]; table++ ) { if ( strncasecomp( &table->name[0], name, (int)len ) == 0 ) { found = table; if ( strcasecomp( &table->name[0], name ) == 0 ) { match = 1; break; } else match++; } // table++; } if ( match == 1 ) { result[0] = found->value; return 0; } table++; } return 0; }
int LYStringToKeycode( char *src ) { unsigned int n; int key = -1; int len = strlen( src ); if ( len == 1 ) key = src[0]; else if ( len == 2 && src[0] == '^' ) key = src[1] & 31; else if ( len > 2 && strncasecomp( src, "0x", 2 ) == 0 ) { char *dst = 0; key = strtol( src, &dst, 0 ); if ( dst && dst[0] ) key = -1; } else if ( len > 6 && strncasecomp( src, "key-", 4 ) == 0 ) { char *dst = 0; key = strtol( &src[4], &dst, 0 ); if ( dst == 0 || dst[0] == 0 ) key = -1; } if ( key < 0 ) { n = 0; for ( ; n <= 23; n++ ) { if ( strcasecomp( named_keys[ n ].name, src ) == 0 ) { key = named_keys[ n ].key; break; } else { // n++; } } } return key; }
/* Helper function - added by MP. */ PRIVATE char* UnReSubject (char* subject) { if (strlen(subject) >= 3 && strncasecomp(subject, "re:", 3) == 0) { char* p = subject + 3; /* "Re:XXX" */ if (*p == ' ') p ++; /* "Re: XXX" */ return p; } return subject; }
char *HTAssocList_lookup(HTAssocList *alist, const char *name) { HTAssocList *cur = alist; HTAssoc *assoc; while (NULL != (assoc = (HTAssoc *) HTList_nextObject(cur))) { if (!strncasecomp(assoc->name, name, (int) strlen(name))) return assoc->value; } return NULL; }
/* Date and Time Parser ** -------------------- ** These functions are taken from the server written by Ari Luotonen */ static int make_month (char* s, char** ends) { char* ptr = s; while (!isalpha((int) *ptr)) ptr++; if (*ptr) { int i; *ends = ptr+3; for (i=0; i<12; i++) if (!strncasecomp(months[i], ptr, 3)) return i; } return 0; }
PUBLIC char * HTAssocList_findObject (HTAssocList * list, const char * name) { if (list && name) { HTAssocList * cur = list; HTAssoc * assoc; int len = strlen(name); while ((assoc = (HTAssoc *) HTList_nextObject(cur))) { if (!strncasecomp(assoc->name, name, len)) return assoc->value; } } return NULL; }
/* Added by MP. */ PUBLIC BOOL HTNewsDir_belongsToSet (HTNewsDir* dir, char* group) { char* p; if (!dir->name || !*(dir->name)) return YES; p = strrchr(dir->name, '*'); if (!p) return strcasecomp(group, dir->name) == 0; else { int len = p - dir->name; return strncasecomp(group, dir->name, len) == 0; } }
/* Helper function added by MP. */ PRIVATE char* GetNewsGroupTitle (HTRequest* request) { char * url = HTAnchor_physical(HTRequest_anchor(request)); char * title = NULL; if (strrchr(url, '*')) StrAllocCopy(title, "Newsgroups: "); else StrAllocCopy(title, "Newsgroup: "); if (!strncasecomp(url, "news:", 5)) StrAllocCat(title, url+5); else StrAllocCat(title, HTParse(url, "", PARSE_PATH)); return title; }
PUBLIC NET_StreamClass * NET_ProxyConverter(int format_out, void *data_obj, URL_Struct *URL_s, MWContext *window_id) { NET_StreamClass* stream; ProxyObj * obj; TRACEMSG(("Setting up display stream. Have URL: %s \n%s\n", URL_s->address, URL_s->content_type)); stream = XP_NEW(NET_StreamClass); if(stream == NULL) return(NULL); obj = XP_NEW(ProxyObj); if(obj == NULL) { FREE(stream); return(NULL); } XP_MEMSET(obj, 0, sizeof(ProxyObj)); stream->data_object = obj; stream->name = "ProxyWriter"; stream->complete = (MKStreamCompleteFunc) net_proxy_complete; stream->abort = (MKStreamAbortFunc) net_proxy_abort; stream->put_block = (MKStreamWriteFunc) net_proxy_write; stream->is_write_ready = (MKStreamWriteReadyFunc) net_proxy_WriteReady; stream->window_id = window_id; TRACEMSG(("Returning stream from display_converter\n")); /* send HTTP headers if not already getting an HTTP doc */ if(strncasecomp(URL_s->address,"http:",5)) { obj->definately_send_headers = TRUE; } StrAllocCopy(obj->content_type, URL_s->content_type); StrAllocCopy(obj->content_encoding, URL_s->content_encoding); return stream; }
/* ** Searches the whole list and removes all elements with this name */ PUBLIC BOOL HTAssocList_removeObject (HTAssocList * list, const char * name) { BOOL found = NO; if (list && name) { HTAssocList * cur = list; HTAssoc * assoc; int len = strlen(name); while ((assoc = (HTAssoc *) HTList_nextObject(cur))) { if (!strncasecomp(assoc->name, name, len)) { HTList_removeObject(list, assoc); HT_FREE(assoc); found = YES; cur = list; } } } return found; }
PUBLIC BOOL HTAssocList_replaceObject (HTAssocList * list, const char * name, const char * value) { if (list && name) { HTAssocList * cur = list; HTAssoc * assoc; int len = strlen(name); while ((assoc = (HTAssoc *) HTList_nextObject(cur))) { if (!strncasecomp(assoc->name, name, len)) { StrAllocCopy(assoc->name, name); if (value) StrAllocCopy(assoc->value, value); return YES; } } return HTAssocList_addObject(list, name, value); } return NO; }
PRIVATE BOOL is_html (char * buf) { char * p = strchr(buf,'<'); if (p && (!strncasecomp(p, "<HTML>", 6) || !strncasecomp(p, "<!DOCTYPE HTML", 13) || !strncasecomp(p, "<HEAD", 5) || !strncasecomp(p, "<TITLE>", 7) || !strncasecomp(p, "<BODY>", 6) || !strncasecomp(p, "<PLAINTEXT>", 11) || (p[0]=='<' && TOUPPER(p[1]) == 'H' && p[3]=='>'))) return YES; else return NO; }
Kcmd *LYStringToKcmd( char *name ) { unsigned int need = strlen( name ); unsigned int j; BOOLEAN exact = 0; Kcmd *result = 0; Kcmd *maybe = 0; if ( name && name[0] ) { j = 0; for ( ; revmap[ j ].name; j++ ) { if ( strcasecomp( revmap[ j ].name, name ) == 0 ) { result = &revmap[ j ]; break; } else { if ( exact == 0 && strncasecomp( revmap[ j ].name, name, (int)need ) == 0 ) { if ( maybe == 0 ) maybe = &revmap[ j ]; else if ( revmap[ j ].name[ need ] && maybe->name[ need ] ) { maybe = 0; exact = 1; } } // j++; } } } return maybe; }
/* Load by name HTLoadFinger * ============ */ int HTLoadFinger(const char *arg, HTParentAnchor *anAnchor, HTFormat format_out, HTStream *stream) { static char empty[1]; char *username, *sitename; /* Fields extracted from URL */ char *slash, *at_sign; /* Fields extracted from URL */ char *command, *str, *param; /* Buffers */ int port; /* Port number from URL */ int status; /* tcp return */ int result = HT_LOADED; BOOL IsGopherURL = FALSE; const char *p1 = arg; CTRACE((tfp, "HTFinger: Looking for %s\n", (arg ? arg : "NULL"))); if (!(arg && *arg)) { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; /* Ignore if no name */ } if (!initialized) initialized = initialize(); if (!initialized) { HTAlert(gettext("Could not set up finger connection.")); return HT_NOT_LOADED; /* FAIL */ } /* Set up the host and command fields. */ if (!strncasecomp(arg, "finger://", 9)) { p1 = arg + 9; /* Skip "finger://" prefix */ } else if (!strncasecomp(arg, "gopher://", 9)) { p1 = arg + 9; /* Skip "gopher://" prefix */ IsGopherURL = TRUE; } param = 0; sitename = StrAllocCopy(param, p1); if (param == 0) { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; } else if ((slash = StrChr(sitename, '/')) != NULL) { *slash++ = '\0'; HTUnEscape(slash); if (IsGopherURL) { if (*slash != '0') { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; /* FAIL */ } *slash++ = '\0'; } } if ((at_sign = StrChr(sitename, '@')) != NULL) { if (IsGopherURL) { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; /* FAIL */ } else { *at_sign++ = '\0'; username = sitename; sitename = at_sign; HTUnEscape(username); } } else if (slash) { username = slash; } else { username = empty; } if (*sitename == '\0') { HTAlert(gettext("Could not load data (no sitename in finger URL)")); result = HT_NOT_LOADED; /* Ignore if no name */ } else if (HTParsePort(sitename, &port) != NULL) { if (port != 79) { HTAlert(gettext("Invalid port number - will only use port 79!")); result = HT_NOT_LOADED; /* Ignore if wrong port */ } } if (result == HT_LOADED) { /* Load the string for making a connection/ */ str = 0; HTSprintf0(&str, "lose://%s/", sitename); /* Load the command for the finger server. */ command = 0; if (at_sign && slash) { if (*slash == 'w' || *slash == 'W') { HTSprintf0(&command, "/w %s%c%c", username, CR, LF); } else { HTSprintf0(&command, "%s%c%c", username, CR, LF); } } else if (at_sign) { HTSprintf0(&command, "%s%c%c", username, CR, LF); } else if (*username == '/') { if ((slash = StrChr((username + 1), '/')) != NULL) { *slash = ' '; } HTSprintf0(&command, "%s%c%c", username, CR, LF); } else if ((*username == 'w' || *username == 'W') && *(username + 1) == '/') { if (*username + 2 != '\0') { *(username + 1) = ' '; } else { *(username + 1) = '\0'; } HTSprintf0(&command, "/%s%c%c", username, CR, LF); } else if ((*username == 'w' || *username == 'W') && *(username + 1) == '\0') { HTSprintf0(&command, "/%s%c%c", username, CR, LF); } else if ((slash = StrChr(username, '/')) != NULL) { *slash++ = '\0'; if (*slash == 'w' || *slash == 'W') { HTSprintf0(&command, "/w %s%c%c", username, CR, LF); } else { HTSprintf0(&command, "%s%c%c", username, CR, LF); } } else { HTSprintf0(&command, "%s%c%c", username, CR, LF); } /* Now, let's get a stream setup up from the FingerHost: * CONNECTING to finger host */ CTRACE((tfp, "HTFinger: doing HTDoConnect on '%s'\n", str)); status = HTDoConnect(str, "finger", FINGER_PORT, &finger_fd); CTRACE((tfp, "HTFinger: Done DoConnect; status %d\n", status)); if (status == HT_INTERRUPTED) { /* Interrupt cleanly */ CTRACE((tfp, "HTFinger: Interrupted on connect; recovering cleanly.\n")); HTProgress(CONNECTION_INTERRUPTED); result = HT_NOT_LOADED; } else if (status < 0) { NETCLOSE(finger_fd); finger_fd = -1; CTRACE((tfp, "HTFinger: Unable to connect to finger host.\n")); HTAlert(gettext("Could not access finger host.")); result = HT_NOT_LOADED; /* FAIL */ } else { CTRACE((tfp, "HTFinger: Connected to finger host '%s'.\n", str)); /* Send the command, and process response if successful. */ if (response(command, sitename, anAnchor, format_out, stream) != 0) { HTAlert(gettext("No response from finger server.")); result = HT_NOT_LOADED; } } FREE(str); FREE(command); } FREE(param); return result; }
/* Scan a filename for its consituents. scan() ** ------------------------------------ ** ** On entry, ** name points to a document name which may be incomplete. ** On exit, ** absolute or relative may be nonzero (but not both). ** host, anchor and access may be nonzero if they were specified. ** Any which are nonzero point to zero terminated strings. */ PRIVATE void scan ARGS2(char *, name, struct struct_parts *, parts) { char *after_access; char *p; /* int length = strlen (name); */ parts->access = NULL; parts->host = NULL; parts->absolute = NULL; parts->relative = NULL; parts->anchor = NULL; /* ** Scan left-to-right for a scheme (access). */ after_access = name; for (p = name; *p; p++) { if (*p == ':') { *p = '\0'; parts->access = name; /* Access name has been specified */ after_access = (p + 1); break; } if (*p == '/' || *p == '#' || *p == ';' || *p == '?') break; } #ifdef NOTDEFINED for (p = (name + length - 1); p >= name; p--) { #endif /* NOTDEFINED */ /* ** Scan left-to-right for a fragment (anchor). */ for (p = after_access; *p; p++) { if (*p == '#') { parts->anchor = (p + 1); *p = '\0'; /* terminate the rest */ } } /* ** Scan left-to-right for a host or absolute path. */ p = after_access; if (*p == '/') { if (p[1] == '/') { parts->host = (p + 2); /* host has been specified */ *p = '\0'; /* Terminate access */ p = strchr(parts->host, '/'); /* look for end of host name if any */ if (p != NULL) { *p = '\0'; /* Terminate host */ parts->absolute = (p + 1); /* Root has been found */ } } else { parts->absolute = (p + 1); /* Root found but no host */ } } else { parts->relative = (*after_access) ? after_access : NULL; /* NULL for * "" */ } /* ** Check schemes that commonly have unescaped hashes. */ if (parts->access && parts->anchor) { if ((!parts->host && strcasecomp(parts->access, "lynxcgi")) || !strcasecomp(parts->access, "nntp") || !strcasecomp(parts->access, "snews") || !strcasecomp(parts->access, "news") || !strcasecomp(parts->access, "data")) { /* * Access specified but no host and not a lynxcgi URL, so the * anchor may not really be one, e.g., news:j462#[email protected], * or it's an nntp or snews URL, or news URL with a host. * Restore the '#' in the address. */ *(parts->anchor - 1) = '#'; parts->anchor = NULL; } } #ifdef NOT_DEFINED /* search is just treated as part of path */ { char *p = (relative ? relative : absolute); if (p != NULL) { char *q = strchr(p, '?'); /* Any search string? */ if (q != NULL) { *q = '\0'; /* If so, chop that off. */ parts->search = (q + 1); } } } #endif /* NOT_DEFINED */ } /* scan */ /* Parse a Name relative to another name. HTParse() ** -------------------------------------- ** ** This returns those parts of a name which are given (and requested) ** substituting bits from the related name where necessary. ** ** On entry, ** aName A filename given ** relatedName A name relative to which aName is to be parsed ** wanted A mask for the bits which are wanted. ** ** On exit, ** returns A pointer to a malloc'd string which MUST BE FREED */ PUBLIC char *HTParse ARGS3(CONST char *, aName, CONST char *, relatedName, int, wanted) { char *result = NULL; char *return_value = NULL; int len; char *name = NULL; char *rel = NULL; char *p; char *access; struct struct_parts given, related; if (TRACE) fprintf(stderr, "HTParse: aName:%s relatedName:%s\n", aName, relatedName); /* ** Allocate the output string. */ len = strlen(aName) + strlen(relatedName) + 10; result = (char *) malloc(len); /* Lots of space: more than enough */ if (result == NULL) outofmem(__FILE__, "HTParse"); result[0] = '\0'; /* Clear string */ /* ** Make working copies of the input strings to cut up. */ StrAllocCopy(name, aName); StrAllocCopy(rel, relatedName); /* ** Cut up the strings into URL fields. */ scan(name, &given); scan(rel, &related); /* ** Handle the scheme (access) field. */ if (given.access && given.host && !given.relative && !given.absolute) { if (!strcmp(given.access, "http") || !strcmp(given.access, "https") || !strcmp(given.access, "ftp")) /* ** Assume root. */ given.absolute = ""; } access = given.access ? given.access : related.access; if (wanted & PARSE_ACCESS) { if (access) { strcat(result, access); if (wanted & PARSE_PUNCTUATION) strcat(result, ":"); } } /* ** If different schemes, inherit nothing. ** ** We'll try complying with RFC 1808 and ** the Fielding draft, and inherit nothing ** if both schemes are given, rather than ** only when they differ, except for ** file URLs - FM ** ** After trying it for a while, it's still ** premature, IHMO, to go along with it, so ** this is back to inheriting for identical ** schemes whether or not they are "file". ** If you want to try it again yourself, ** uncomment the strncasecomp() below. - FM */ if ((given.access && related.access) && ( /* strcasecomp(given.access, * "file") || */ strcmp(given.access, related.access))) { related.host = NULL; related.absolute = NULL; related.relative = NULL; related.anchor = NULL; } /* ** Handle the host field. */ if (wanted & PARSE_HOST) if (given.host || related.host) { char *tail = result + strlen(result); if (wanted & PARSE_PUNCTUATION) strcat(result, "//"); strcat(result, given.host ? given.host : related.host); #define CLEAN_URLS #ifdef CLEAN_URLS /* ** Ignore default port numbers, and trailing dots on FQDNs, ** which will only cause identical addresses to look different. */ { char *p, *h; p = strchr(tail, ':'); if (p != NULL && !isdigit((unsigned char) p[1])) /* ** Colon not followed by a port number. */ *p = '\0'; if (p != NULL && p != '\0' && access != NULL) { /* ** Port specified. */ if ((!strcmp(access, "http") && !strcmp(p, ":80")) || (!strcmp(access, "gopher") && !strcmp(p, ":70")) || (!strcmp(access, "ftp") && !strcmp(p, ":21")) || (!strcmp(access, "wais") && !strcmp(p, ":210")) || (!strcmp(access, "nntp") && !strcmp(p, ":119")) || (!strcmp(access, "news") && !strcmp(p, ":119")) || (!strcmp(access, "snews") && !strcmp(p, ":563")) || (!strcmp(access, "finger") && !strcmp(p, ":79")) || (!strcmp(access, "cso") && !strcmp(p, ":105"))) *p = '\0'; /* It is the default: ignore it */ } if (p == NULL) { int len = strlen(tail); if (len > 0) { h = tail + len - 1; /* last char of hostname */ if (*h == '.') *h = '\0'; /* chop final . */ } } else { h = p; h--; /* End of hostname */ if (*h == '.') { /* ** Slide p over h. */ while (*p != '\0') *h++ = *p++; *h = '\0'; /* terminate */ } } } #endif /* CLEAN_URLS */ } /* ** If different hosts, inherit no path. */ if (given.host && related.host) if (strcmp(given.host, related.host) != 0) { related.absolute = NULL; related.relative = NULL; related.anchor = NULL; } /* ** Handle the path. */ if (wanted & PARSE_PATH) { if (access && !given.absolute && given.relative) { if (!strcasecomp(access, "nntp") || !strcasecomp(access, "snews") || (!strcasecomp(access, "news") && !strncasecomp(result, "news://", 7))) { /* * Treat all given nntp or snews paths, * or given paths for news URLs with a host, * as absolute. */ given.absolute = given.relative; given.relative = NULL; } } if (given.absolute) { /* All is given */ if (wanted & PARSE_PUNCTUATION) strcat(result, "/"); strcat(result, given.absolute); if (TRACE) fprintf(stderr, "1\n"); } else if (related.absolute) { /* Adopt path not name */ strcat(result, "/"); strcat(result, related.absolute); if (given.relative) { p = strchr(result, '?'); /* Search part? */ if (p == NULL) p = (result + strlen(result) - 1); for (; *p != '/'; p--); /* last / */ p[1] = '\0'; /* Remove filename */ strcat(result, given.relative); /* Add given one */ HTSimplify(result); } if (TRACE) fprintf(stderr, "2\n"); } else if (given.relative) { strcat(result, given.relative); /* what we've got */ if (TRACE) fprintf(stderr, "3\n"); } else if (related.relative) { strcat(result, related.relative); if (TRACE) fprintf(stderr, "4\n"); } else { /* No inheritance */ if (strncasecomp(aName, "lynxcgi:", 8) && strncasecomp(aName, "lynxexec:", 9) && strncasecomp(aName, "lynxprog:", 9)) { strcat(result, "/"); } if (!strcmp(result, "news:/")) result[5] = '*'; if (TRACE) fprintf(stderr, "5\n"); } } /* ** Handle the fragment (anchor). */ if (wanted & PARSE_ANCHOR) if ((given.anchor && *given.anchor) || (!given.anchor && related.anchor)) { if (wanted & PARSE_PUNCTUATION) strcat(result, "#"); strcat(result, (given.anchor) ? given.anchor : related.anchor); } if (TRACE) fprintf(stderr, "HTParse: result:%s\n", result); FREE(rel); FREE(name); StrAllocCopy(return_value, result); FREE(result); return return_value; /* exactly the right length */ }
/* ** mailmsg() sends a message to the owner of the file, if one is defined, ** telling of errors (i.e., link not available). */ PUBLIC void mailmsg ARGS4( int, cur, char *, owner_address, char *, filename, char *, linkname) { FILE *fd, *fp; char *address = NULL; char *searchpart = NULL; char *cmd = NULL, *cp; #ifdef ALERTMAIL BOOLEAN skip_parsing = FALSE; #endif #if !CAN_PIPE_TO_MAILER char *ccaddr; char subject[128]; char my_tmpfile[LY_MAXPATH]; #endif #if USE_VMS_MAILER BOOLEAN isPMDF = LYMailPMDF(); char hdrfile[LY_MAXPATH]; char *command = NULL; CTRACE((tfp, "mailmsg(%d, \"%s\", \"%s\", \"%s\")\n", cur, NONNULL(owner_address), NONNULL(filename), NONNULL(linkname))); #endif /* VMS */ if (!LYSystemMail()) return; #ifdef ALERTMAIL if (owner_address == NULL) { owner_address = ALERTMAIL; skip_parsing = TRUE; } #endif if (isEmpty(owner_address)) return; if ((cp = (char *)strchr(owner_address,'\n')) != NULL) { #ifdef ALERTMAIL if (skip_parsing) return; /* invalidly defined - ignore - kw */ #else *cp = '\0'; #endif } if (!strncasecomp(owner_address, "lynx-dev@", 9)) { /* * Silently refuse sending bad link messages to lynx-dev. */ return; } StrAllocCopy(address, owner_address); #ifdef ALERTMAIL /* * If we are using a fixed address given by ALERTMAIL, it is * supposed to already be in usable form, without URL-isms like * ?-searchpart and URL-escaping. So skip some code. - kw */ if (!skip_parsing) #endif { /* * Check for a ?searchpart. - FM */ if ((cp = strchr(address, '?')) != NULL) { StrAllocCopy(searchpart, cp); *cp = '\0'; cp = (searchpart + 1); if (*cp != '\0') { /* * Seek and handle to=address(es) fields. * Appends to address. We ignore any other * headers in the ?searchpart. - FM */ extract_field(&address, searchpart, "to="); } } convert_explorer(address); /* * Unescape the address field. - FM */ SafeHTUnEscape(address); } if (trim_comma(address)) { FREE(address); CTRACE((tfp, "mailmsg: No address in '%s'.\n", owner_address)); return; } #if CAN_PIPE_TO_MAILER if ((fd = LYPipeToMailer()) == 0) { FREE(address); CTRACE((tfp, "mailmsg: '%s' failed.\n", cmd)); return; } fprintf(fd, "To: %s\n", address); fprintf(fd, "Subject: Lynx Error in %s\n", filename); if (!isEmpty(personal_mail_address)) { fprintf(fd, "Cc: %s\n", personal_mail_address); } fprintf(fd, "X-URL: %s\n", filename); fprintf(fd, "X-Mailer: %s, Version %s\n\n", LYNX_NAME, LYNX_VERSION); #else if ((fd = LYOpenTemp(my_tmpfile, ".txt", "w")) == NULL) { CTRACE((tfp, "mailmsg: Could not fopen '%s'.\n", my_tmpfile)); FREE(address); return; } sprintf(subject, "Lynx Error in %.56s", filename); ccaddr = personal_mail_address; #if USE_VMS_MAILER if (isPMDF) { FILE *hfd; if ((hfd = LYOpenTemp(hdrfile, ".txt", "w")) == NULL) { CTRACE((tfp, "mailmsg: Could not fopen '%s'.\n", hdrfile)); FREE(address); return; } if (!isEmpty(personal_mail_address)) { fprintf(fd, "Cc: %s\n", personal_mail_address); } fprintf(fd, "X-URL: %s\n", filename); fprintf(fd, "X-Mailer: %s, Version %s\n\n", LYNX_NAME, LYNX_VERSION); /* * For PMDF, put the subject in the * header file and close it. - FM */ fprintf(hfd, "Subject: Lynx Error in %.56s\n\n", filename); LYCloseTempFP(hfd); } #endif /* USE_VMS_MAILER */ #endif /* CAN_PIPE_TO_MAILER */ fprintf(fd, gettext("The link %s :?: %s \n"), links[cur].lname, links[cur].target); fprintf(fd, gettext("called \"%s\"\n"), LYGetHiliteStr(cur, 0)); fprintf(fd, gettext("in the file \"%s\" called \"%s\"\n"), filename, linkname); fprintf(fd, "%s\n\n", gettext("was requested but was not available.")); fprintf(fd, "%s\n\n", gettext("Thought you might want to know.")); fprintf(fd, "%s\n", gettext("This message was automatically generated by")); fprintf(fd, "%s %s", LYNX_NAME, LYNX_VERSION); if ((LynxSigFile != NULL) && (fp = fopen(LynxSigFile, TXT_R)) != NULL) { fputs("-- \n", fd); while (LYSafeGets(&cmd, fp) != NULL) fputs(cmd, fd); LYCloseInput(fp); } #if CAN_PIPE_TO_MAILER pclose(fd); #else LYCloseTempFP(fd); #if USE_VMS_MAILER if (isPMDF) { /* * Now set up the command. - FM */ HTSprintf0(&command, "%s %s %s,%s ", system_mail, system_mail_flags, hdrfile, my_tmpfile); } else { /* * For "generic" VMS MAIL, include the * subject in the command. - FM */ HTSprintf0(&command, "%s %s/self/subject=\"Lynx Error in %.56s\" %s ", system_mail, system_mail_flags, filename, my_tmpfile); } vms_append_addrs(&command, address, ""); LYSystem(command); /* VMS */ FREE(command); FREE(cmd); LYRemoveTemp(my_tmpfile); if (isPMDF) { LYRemoveTemp(hdrfile); } #else /* DOS */ LYSendMailFile ( address, my_tmpfile, subject, ccaddr, ""); LYRemoveTemp(my_tmpfile); #endif /* USE_VMS_MAILER */ #endif /* CAN_PIPE_TO_MAILER */ if (traversal) { FILE *ofp; if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) { if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) { perror(NOOPEN_TRAV_ERR_FILE); exit_immediately(EXIT_FAILURE); } } fprintf(ofp, "%s\t%s \tin %s\n", links[cur].lname, links[cur].target, filename); LYCloseOutput(ofp); } FREE(address); return; }
PUBLIC BOOLEAN LYMailPMDF(void) { return (system_mail != 0) ? !strncasecomp(system_mail, "PMDF SEND", 9) : FALSE; }
/* ** mailform() sends form content to the mailto address(es). - FM */ PUBLIC void mailform ARGS4( CONST char *, mailto_address, CONST char *, mailto_subject, CONST char *, mailto_content, CONST char *, mailto_type) { FILE *fd; char *address = NULL; char *ccaddr = NULL; char *keywords = NULL; char *cp = NULL; char self[MAX_SUBJECT + 10]; char subject[MAX_SUBJECT + 10]; char *searchpart = NULL; char buf[512]; int ch, len, i; #if USE_VMS_MAILER static char *cmd; char *command = NULL; BOOLEAN isPMDF = LYMailPMDF(); char hdrfile[LY_MAXPATH]; #endif #if !CAN_PIPE_TO_MAILER char my_tmpfile[LY_MAXPATH]; #endif CTRACE((tfp, "mailto_address: \"%s\"\n", NONNULL(mailto_address))); CTRACE((tfp, "mailto_subject: \"%s\"\n", NONNULL(mailto_subject))); CTRACE((tfp, "mailto_content: \"%s\"\n", NONNULL(mailto_content))); CTRACE((tfp, "mailto_type: \"%s\"\n", NONNULL(mailto_type))); if (!LYSystemMail()) return; if (!mailto_address || !mailto_content) { HTAlert(BAD_FORM_MAILTO); return; } subject[0] = '\0'; self[0] = '\0'; if ((cp = (char *)strchr(mailto_address,'\n')) != NULL) *cp = '\0'; StrAllocCopy(address, mailto_address); /* * Check for a ?searchpart. - FM */ if ((cp = strchr(address, '?')) != NULL) { StrAllocCopy(searchpart, cp); *cp = '\0'; cp = (searchpart + 1); if (*cp != '\0') { /* * Seek and handle a subject=foo. - FM */ extract_subject(subject, searchpart); /* * Seek and handle to=address(es) fields. * Appends to address. - FM */ extract_field(&address, searchpart, "to="); /* * Seek and handle cc=address(es) fields. Excludes * Bcc=address(es) as unsafe. We may append our own * cc (below) as a list for the actual mailing. - FM */ extract_field(&ccaddr, searchpart, "cc="); /* * Seek and handle keywords=term(s) fields. - FM */ extract_field(&keywords, searchpart, "keywords="); if (keywords != NULL) { if (*keywords != '\0') { SafeHTUnEscape(keywords); } else { FREE(keywords); } } FREE(searchpart); } } if (convert_explorer(address)) { HTAlert(BAD_FORM_MAILTO); goto cleanup; } if (ccaddr != NULL) { if (convert_explorer(ccaddr)) { FREE(ccaddr); } } /* * Unescape the address and ccaddr fields. - FM */ SafeHTUnEscape(address); if (ccaddr != NULL) { SafeHTUnEscape(ccaddr); } /* * Allow user to edit the default Subject - FM */ if (isEmpty(subject)) { if (!isEmpty(mailto_subject)) { LYstrncpy(subject, mailto_subject, MAX_SUBJECT); } else { sprintf(subject, "mailto:%.63s", address); } } _statusline(SUBJECT_PROMPT); if ((ch = LYgetstr(subject, VISIBLE, MAX_SUBJECT, NORECALL)) < 0) { /* * User cancelled via ^G. - FM */ HTInfoMsg(FORM_MAILTO_CANCELLED); goto cleanup; } /* * Allow user to specify a self copy via a CC: * entry, if permitted. - FM */ if (!LYNoCc) { sprintf(self, "%.*s", MAX_SUBJECT, isEmpty(personal_mail_address) ? "" : personal_mail_address); _statusline("Cc: "); if ((ch = LYgetstr(self, VISIBLE, MAX_SUBJECT, NORECALL)) < 0) { /* * User cancelled via ^G. - FM */ HTInfoMsg(FORM_MAILTO_CANCELLED); goto cleanup; } remove_tildes(self); if (ccaddr == NULL) { StrAllocCopy(ccaddr, self); } else { StrAllocCat(ccaddr, ","); StrAllocCat(ccaddr, self); } } #if CAN_PIPE_TO_MAILER if ((fd = LYPipeToMailer()) == 0) { HTAlert(FORM_MAILTO_FAILED); goto cleanup; } if (!isEmpty(mailto_type)) { fprintf(fd, "Mime-Version: 1.0\n"); fprintf(fd, "Content-Type: %s\n", mailto_type); } fprintf(fd, "To: %s\n", address); if (!isEmpty(personal_mail_address)) fprintf(fd, "From: %s\n", personal_mail_address); if (!isEmpty(ccaddr)) fprintf(fd, "Cc: %s\n", ccaddr); fprintf(fd, "Subject: %s\n\n", subject); if (!isEmpty(keywords)) fprintf(fd, "Keywords: %s\n", keywords); _statusline(SENDING_FORM_CONTENT); #else /* e.g., VMS, DOS */ if ((fd = LYOpenTemp(my_tmpfile, ".txt", "w")) == NULL) { HTAlert(FORM_MAILTO_FAILED); goto cleanup; } #if USE_VMS_MAILER if (isPMDF) { FILE *hfd; if ((hfd = LYOpenTemp(hdrfile, ".txt", "w")) == NULL) { HTAlert(FORM_MAILTO_FAILED); LYCloseTempFP(fd); goto cleanup; } if (!isEmpty(mailto_type)) { fprintf(hfd, "Mime-Version: 1.0\n"); fprintf(hfd, "Content-Type: %s\n", mailto_type); if (!isEmpty(personal_mail_address)) fprintf(hfd, "From: %s\n", personal_mail_address); } /* * For PMDF, put any keywords and the subject * in the header file and close it. - FM */ if (!isEmpty(keywords)) { fprintf(hfd, "Keywords: %s\n", keywords); } fprintf(hfd, "Subject: %s\n\n", subject); LYCloseTempFP(hfd); } else if (mailto_type && !strncasecomp(mailto_type, "multipart/form-data", 19)) { /* * Ugh! There's no good way to include headers while * we're still using "generic" VMS MAIL, so we'll put * this in the body of the message. - FM */ fprintf(fd, "X-Content-Type: %s\n\n", mailto_type); } #else /* !VMS (DOS) */ #if USE_BLAT_MAILER if (mail_is_blat) { if (strlen(subject) > MAX_SUBJECT) subject[MAX_SUBJECT] = '\0'; } else #endif { if (!isEmpty(mailto_type)) { fprintf(fd, "Mime-Version: 1.0\n"); fprintf(fd, "Content-Type: %s\n", mailto_type); } fprintf(fd,"To: %s\n", address); if (!isEmpty(personal_mail_address)) fprintf(fd,"From: %s\n", personal_mail_address); fprintf(fd,"Subject: %.70s\n\n", subject); } #endif /* VMS */ #endif /* CAN_PIPE_TO_MAILER */ /* * Break up the content into lines with a maximum length of 78. * If the ENCTYPE was text/plain, we have physical newlines and * should take them into account. Otherwise, the actual newline * characters in the content are hex escaped. - FM */ while((cp = strchr(mailto_content, '\n')) != NULL) { *cp = '\0'; i = 0; len = strlen(mailto_content); while (len > 78) { strncpy(buf, &mailto_content[i], 78); buf[78] = '\0'; fprintf(fd, "%s\n", buf); i += 78; len = strlen(&mailto_content[i]); } fprintf(fd, "%s\n", &mailto_content[i]); mailto_content = (cp+1); } i = 0; len = strlen(mailto_content); while (len > 78) { strncpy(buf, &mailto_content[i], 78); buf[78] = '\0'; fprintf(fd, "%s\n", buf); i += 78; len = strlen(&mailto_content[i]); } if (len) fprintf(fd, "%s\n", &mailto_content[i]); #if CAN_PIPE_TO_MAILER pclose(fd); LYSleepMsg(); #else LYCloseTempFP(fd); #if USE_VMS_MAILER /* * Set the mail command. - FM */ if (isPMDF) { /* * Now set up the command. - FM */ HTSprintf0(&cmd, "%s %s %s,%s ", system_mail, system_mail_flags, hdrfile, my_tmpfile); } else { /* * For "generic" VMS MAIL, include the subject in the * command, and ignore any keywords to minimize risk * of them making the line too long or having problem * characters. - FM */ HTSprintf0(&cmd, "%s %s%s/subject=\"%s\" %s ", system_mail, system_mail_flags, (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"), subject, my_tmpfile); } StrAllocCopy(command, cmd); vms_append_addrs(&command, address, ""); if (!isEmpty(ccaddr)) { vms_append_addrs(&command, ccaddr, "/CC"); } stop_curses(); printf("%s\n\n$ %s\n\n%s", SENDING_FORM_CONTENT, command, PLEASE_WAIT); LYSystem(command); /* Mail (VMS) */ FREE(command); LYSleepAlert(); start_curses(); LYRemoveTemp(my_tmpfile); if (isPMDF) LYRemoveTemp(hdrfile); #else /* DOS */ LYSendMailFile ( address, my_tmpfile, subject, ccaddr, SENDING_FORM_CONTENT); LYRemoveTemp(my_tmpfile); #endif /* USE_VMS_MAILER */ #endif /* CAN_PIPE_TO_MAILER */ cleanup: FREE(address); FREE(ccaddr); FREE(keywords); return; }
/* * Seek and handle body=foo fields. - FM */ PRIVATE void extract_body ARGS2( char **, dst, char *, src) { CONST char *keyword = "body="; int len = strlen(keyword); int i; char *cp, *cp0, *cp1, *temp = 0; cp = (src + 1); while (*cp != '\0') { if ((*(cp - 1) == '?' || *(cp - 1) == '&') && !strncasecomp(cp, keyword, len)) { cp += len; if ((cp1 = strchr(cp, '&')) != NULL) { *cp1 = '\0'; } if (*cp) { /* * Break up the value into lines with * a maximum length of 78. - FM */ StrAllocCopy(temp, cp); HTUnEscape(temp); cp0 = temp; while((cp = strchr(cp0, '\n')) != NULL) { *cp = '\0'; if (cp > cp0) { if (*(cp - 1) == '\r') { *(cp - 1) = '\0'; } } i = 0; len = strlen(cp0); while (len > 78) { HTSprintf(dst, "%.78s\n", &cp0[i]); i += 78; len = strlen(&cp0[i]); } HTSprintf(dst, "%s\n", &cp0[i]); cp0 = (cp + 1); } i = 0; len = strlen(cp0); while (len > 78) { HTSprintf(dst, "%.78s\n", &cp0[i]); i += 78; len = strlen(&cp0[i]); } if (len) { HTSprintf(dst, "%s\n", &cp0[i]); } FREE(temp); } if (cp1) { *cp1 = '&'; cp = cp1; cp1 = NULL; } else { break; } } cp++; } CTRACE((tfp, "extract_body(%s) = '%s'\n", keyword, NONNULL(*dst))); }
/* Load one line of configuration * ------------------------------ * * Call this, for example, to load a X resource with config info. * * returns 0 OK, < 0 syntax error. */ int HTSetConfiguration(char *config) { HTRuleOp op; char *line = NULL; char *pointer = line; char *word1; const char *word2; const char *word3; const char *cond_op = NULL; const char *cond = NULL; float quality, secs, secs_per_byte; int maxbytes; int status; StrAllocCopy(line, config); { char *p = strchr(line, '#'); /* Chop off comments */ if (p) *p = 0; } pointer = line; word1 = HTNextField(&pointer); if (!word1) { FREE(line); return 0; }; /* Comment only or blank */ word2 = HTNextField(&pointer); if (0 == strcasecomp(word1, "defprot") || 0 == strcasecomp(word1, "protect")) word3 = pointer; /* The rest of the line to be parsed by AA module */ else word3 = HTNextField(&pointer); /* Just the next word */ if (!word2) { fprintf(stderr, "HTRule: %s %s\n", RULE_NEEDS_DATA, line); FREE(line); return -2; /*syntax error */ } if (0 == strcasecomp(word1, "suffix")) { char *encoding = HTNextField(&pointer); if (pointer) status = sscanf(pointer, "%f", &quality); else status = 0; HTSetSuffix(word2, word3, encoding ? encoding : "binary", status >= 1 ? quality : (float) 1.0); } else if (0 == strcasecomp(word1, "presentation")) { if (pointer) status = sscanf(pointer, "%f%f%f%d", &quality, &secs, &secs_per_byte, &maxbytes); else status = 0; HTSetPresentation(word2, word3, NULL, status >= 1 ? quality : 1.0, status >= 2 ? secs : 0.0, status >= 3 ? secs_per_byte : 0.0, status >= 4 ? maxbytes : 0, mediaCFG); } else if (0 == strncasecomp(word1, "htbin", 5) || 0 == strncasecomp(word1, "bindir", 6)) { StrAllocCopy(HTBinDir, word2); /* Physical /htbin location */ } else if (0 == strncasecomp(word1, "search", 6)) { StrAllocCopy(HTSearchScript, word2); /* Search script name */ } else { op = 0 == strcasecomp(word1, "map") ? HT_Map : 0 == strcasecomp(word1, "pass") ? HT_Pass : 0 == strcasecomp(word1, "fail") ? HT_Fail : 0 == strcasecomp(word1, "redirect") ? HT_Redirect : 0 == strncasecomp(word1, "redirectperm", 12) ? HT_RedirectPerm : 0 == strcasecomp(word1, "redirecttemp") ? HT_Redirect : 0 == strcasecomp(word1, "permitredirection") ? HT_PermitRedir : 0 == strcasecomp(word1, "useproxy") ? HT_UseProxy : 0 == strcasecomp(word1, "alert") ? HT_Alert : 0 == strcasecomp(word1, "alwaysalert") ? HT_AlwaysAlert : 0 == strcasecomp(word1, "progress") ? HT_Progress : 0 == strcasecomp(word1, "usermsg") ? HT_UserMsg : 0 == strcasecomp(word1, "infomsg") ? HT_InfoMsg : 0 == strcasecomp(word1, "defprot") ? HT_DefProt : 0 == strcasecomp(word1, "protect") ? HT_Protect : HT_Invalid; if (op == HT_Invalid) { fprintf(stderr, "HTRule: %s '%s'\n", RULE_INCORRECT, config); } else { switch (op) { case HT_Fail: /* never a or other 2nd parameter */ case HT_PermitRedir: cond_op = word3; if (cond_op && *cond_op) { word3 = NULL; cond = HTNextField(&pointer); } break; case HT_Pass: /* possibly a URL2 */ if (word3 && (!strcasecomp(word3, "if") || !strcasecomp(word3, "unless"))) { cond_op = word3; word3 = NULL; cond = HTNextField(&pointer); break; } /* else fall through */ case HT_Map: /* always a URL2 (or other 2nd parameter) */ case HT_Redirect: case HT_RedirectPerm: case HT_UseProxy: cond_op = HTNextField(&pointer); /* check for extra status word in "Redirect" */ if (op == HT_Redirect && 0 == strcasecomp(word1, "redirect") && cond_op && strcasecomp(cond_op, "if") && strcasecomp(cond_op, "unless")) { if (0 == strcmp(word2, "301") || 0 == strcasecomp(word2, "permanent")) { op = HT_RedirectPerm; } else if (!(0 == strcmp(word2, "302") || 0 == strcmp(word2, "303") || 0 == strcasecomp(word2, "temp") || 0 == strcasecomp(word2, "seeother"))) { CTRACE((tfp, "Rule: Ignoring `%s' in Redirect\n", word2)); } word2 = word3; word3 = cond_op; /* cond_op isn't condition op after all */ cond_op = HTNextField(&pointer); } if (cond_op && *cond_op) cond = HTNextField(&pointer); break; case HT_Progress: case HT_InfoMsg: case HT_UserMsg: case HT_Alert: case HT_AlwaysAlert: cond_op = HTNextField(&pointer); if (cond_op && *cond_op) cond = HTNextField(&pointer); if (word3) { /* Fix string with too may %s - kw */ const char *cp = word3; char *cp1, *cp2; while ((cp1 = strchr(cp, '%'))) { if (cp1[1] == '\0') { *cp1 = '\0'; break; } else if (cp1[1] == '%') { cp = cp1 + 2; continue; } else while ((cp2 = strchr(cp1 + 2, '%'))) { if (cp2[1] == '\0') { *cp2 = '\0'; break; } else if (cp2[1] == '%') { cp1 = cp2; } else { *cp2 = '?'; /* replace bad % */ cp1 = cp2; } } break; } } break; default: break; } if (cond_op && cond && *cond && !strcasecomp(cond_op, "unless")) { cond_op = "unless"; } else if (cond_op && cond && *cond && !strcasecomp(cond_op, "if")) { cond_op = "if"; } else if (cond_op || cond) { fprintf(stderr, "HTRule: %s '%s'\n", RULE_INCORRECT, config); FREE(line); /* syntax error, condition is a mess - kw */ return -2; /* NB unrecognized cond passes here - kw */ } if (cond && !strncasecomp(cond, "redirected", strlen(cond))) { cond = "redirected"; /* recognized, canonical case - kw */ } else if (cond && strlen(cond) >= 8 && !strncasecomp(cond, "userspecified", strlen(cond))) { cond = "userspec"; /* also allow abbreviation - kw */ } HTAddRule(op, word2, word3, cond_op, cond); } } FREE(line); return 0; }
/* ** reply_by_mail() invokes sendmail on Unix or mail on VMS to send ** a comment from the users to the owner */ PUBLIC void reply_by_mail ARGS4( char *, mail_address, char *, filename, CONST char *, title, CONST char *, refid) { #ifndef NO_ANONYMOUS_EMAIL static char *personal_name = NULL; #endif char user_input[LINESIZE]; FILE *fd, *fp; char *label = NULL; char *from_address = NULL; char *cc_address = NULL; char *to_address = NULL; char *the_subject = NULL; char *ccaddr = NULL; char *keywords = NULL; char *searchpart = NULL; char *body = NULL; char *cp = NULL, *cp1 = NULL; int i; int c = 0; /* user input */ char my_tmpfile[LY_MAXPATH]; char default_subject[MAX_SUBJECT + 10]; #if USE_VMS_MAILER char *command = NULL; BOOLEAN isPMDF = LYMailPMDF(); char hdrfile[LY_MAXPATH]; FILE *hfd = 0; #else #if !CAN_PIPE_TO_MAILER char tmpfile2[LY_MAXPATH]; #endif char buf[4096]; /* 512 */ char *header = NULL; int n; #endif /* USE_VMS_MAILER */ CTRACE((tfp, "reply_by_mail(\"%s\", \"%s\", \"%s\", \"%s\")\n", NONNULL(mail_address), NONNULL(filename), NONNULL(title), NONNULL(refid))); term_letter = FALSE; if (!LYSystemMail()) return; if (isEmpty(mail_address)) { HTAlert(NO_ADDRESS_IN_MAILTO_URL); return; } StrAllocCopy(to_address, mail_address); if ((fd = LYOpenTemp(my_tmpfile, ".txt", "w")) == NULL) { HTAlert(MAILTO_URL_TEMPOPEN_FAILED); return; } #if USE_VMS_MAILER if (isPMDF) { if ((hfd = LYOpenTemp(hdrfile, ".txt", "w")) == NULL) { HTAlert(MAILTO_URL_TEMPOPEN_FAILED); return; } } #endif /* VMS */ default_subject[0] = '\0'; /* * Check for a ?searchpart. - FM */ if ((cp = strchr(to_address, '?')) != NULL) { StrAllocCopy(searchpart, cp); *cp = '\0'; cp = (searchpart + 1); if (*cp != '\0') { /* * Seek and handle a subject=foo. - FM */ extract_subject(default_subject, searchpart); /* * Seek and handle to=address(es) fields. * Appends to address. - FM */ extract_field(&to_address, searchpart, "to="); /* * Seek and handle cc=address(es) fields. Excludes * Bcc=address(es) as unsafe. We may append our own * cc (below) as a list for the actual mailing. - FM */ extract_field(&ccaddr, searchpart, "cc="); /* * Seek and handle keywords=term(s) fields. - FM */ extract_field(&keywords, searchpart, "keywords="); if (keywords != NULL) { if (*keywords != '\0') { SafeHTUnEscape(keywords); } else { FREE(keywords); } } /* * Seek and handle body=foo fields. - FM */ extract_body(&body, searchpart); FREE(searchpart); } } if (convert_explorer(to_address)) { HTAlert(NO_ADDRESS_IN_MAILTO_URL); goto cancelled; } if (ccaddr != NULL) { if (convert_explorer(ccaddr)) { FREE(ccaddr); } } /* * Unescape the address and ccaddr fields. - FM */ SafeHTUnEscape(to_address); if (ccaddr != NULL) { SafeHTUnEscape(ccaddr); } /* * Set the default subject. - FM */ if (isEmpty(default_subject) && !isEmpty(title)) { strncpy(default_subject, title, MAX_SUBJECT); default_subject[MAX_SUBJECT] = '\0'; } /* * Use ^G to cancel mailing of comment * and don't let SIGINTs exit lynx. */ signal(SIGINT, terminate_letter); #if USE_VMS_MAILER if (isPMDF || !body) { /* * Put the X-URL and X-Mailer lines in the hdrfile * for PMDF or my_tmpfile for VMS MAIL. - FM */ fprintf((isPMDF ? hfd : fd), "X-URL: %s%s\n", isEmpty(filename) ? STR_MAILTO_URL : filename, isEmpty(filename) ? to_address : ""); fprintf((isPMDF ? hfd : fd), "X-Mailer: %s, Version %s\n", LYNX_NAME, LYNX_VERSION); #ifdef NO_ANONYMOUS_EMAIL if (!isPMDF) { fprintf(fd, "\n"); } #endif /* NO_ANONYMOUS_EMAIL */ } #else /* Unix/DOS/Windows */ /* * Put the To: line in the header. */ #ifndef DOSPATH asprintf(&header, "To: %s\n", to_address); if (!header) { fprintf(stderr, "Out of memory, you lose!\n"); exit(1); } #endif /* * Put the Mime-Version, Content-Type and * Content-Transfer-Encoding in the header. * This assumes that the same character set is used * for composing the mail which is currently selected * as display character set... * Don't send a charset if we have a CJK character set * selected, since it may not be appropriate for mail... * Also don't use an unofficial "x-" charset. * Also if the charset would be "us-ascii" (7-bit replacements * selected, don't send any MIME headers. - kw */ if (strncasecomp(LYCharSet_UC[current_char_set].MIMEname, "us-ascii", 8) != 0) { StrAllocCat(header, "Mime-Version: 1.0\n"); if (!LYHaveCJKCharacterSet && strncasecomp(LYCharSet_UC[current_char_set].MIMEname, "x-", 2) != 0) { HTSprintf(&header, "Content-Type: text/plain; charset=%s\n", LYCharSet_UC[current_char_set].MIMEname); } StrAllocCat(header, "Content-Transfer-Encoding: 8bit\n"); } /* * Put the X-URL and X-Mailer lines in the header. */ if (!isEmpty(filename)) { HTSprintf(&header, "X-URL: %s\n", filename); } else { HTSprintf(&header, "X-URL: mailto:%s\n", to_address); } HTSprintf(&header, "X-Mailer: %s, Version %s\n", LYNX_NAME, LYNX_VERSION); if (!isEmpty(refid)) { HTSprintf(&header, "In-Reply-To: <%s>\n", refid); } #endif /* VMS */ /* * Clear the screen and inform the user. */ LYclear(); LYmove(2,0); scrollok(LYwin, TRUE); /* Enable scrolling. */ if (body) LYaddstr(SENDING_MESSAGE_WITH_BODY_TO); else LYaddstr(SENDING_COMMENT_TO); show_addresses(to_address); if ( #if USE_VMS_MAILER (isPMDF == TRUE) && #endif /* VMS */ (cp = ccaddr) != NULL) { if (strchr(cp, ',') != NULL) { LYaddstr(WITH_COPIES_TO); } else { LYaddstr(WITH_COPY_TO); } show_addresses(ccaddr); } LYaddstr(CTRL_G_TO_CANCEL_SEND); #if USE_VMS_MAILER if (isPMDF || !body) { #endif /* USE_VMS_MAILER */ #ifndef NO_ANONYMOUS_EMAIL /* * Get the user's personal name. */ LYaddstr(ENTER_NAME_OR_BLANK); #if USE_VMS_MAILER if (isPMDF) { label = "Personal_name: "; } else { label = "X-Personal_name: "; } #else label = "X-Personal_Name: "; #endif /* USE_VMS_MAILER */ if (!header_prompt(label, &personal_name, LINESIZE)) { goto cancelled; } if (*personal_name) { #if USE_VMS_MAILER fprintf((isPMDF ? hfd : fd), "%s: %s\n", label, personal_name); #else HTSprintf(&header, "%s: %s\n", label, personal_name); #endif /* VMS */ } /* * Get the user's return address. */ LYaddstr(ENTER_MAIL_ADDRESS_OR_OTHER); LYaddstr(MEANS_TO_CONTACT_FOR_RESPONSE); #if USE_VMS_MAILER if (isPMDF) { label = "From"; } else { label = "X-From"; } #else label = "From"; #endif /* VMS */ /* Add the personal mail address if there is one. */ if (personal_mail_address) StrAllocCopy(from_address, personal_mail_address); if (!header_prompt(label, &from_address, LINESIZE)) { goto cancelled; } #if USE_VMS_MAILER if (*from_address) { fprintf(isPMDF ? hfd : fd, "%s: %s\n", label, from_address); } if (!isPMDF) { fprintf(fd, "\n"); } #else HTSprintf(&header, "%s: %s\n", label, from_address); #endif /* USE_VMS_MAILER */ #endif /* !NO_ANONYMOUS_EMAIL */ #if USE_VMS_MAILER } #endif /* USE_VMS_MAILER */ /* * Get the subject line. */ LYaddstr(ENTER_SUBJECT_LINE); label = "Subject"; if (*default_subject) { StrAllocCopy(the_subject, default_subject); } else if (!isEmpty(filename)) { HTSprintf(&the_subject, "%s", filename); } else { HTSprintf(&the_subject, "mailto:%s", to_address); } if (!header_prompt(label, &the_subject, MAX_SUBJECT)) { goto cancelled; } /* * Offer a CC line, if permitted. - FM */ if (!LYNoCc) { LYaddstr(ENTER_ADDRESS_FOR_CC); LYaddstr(BLANK_FOR_NO_COPY); if (personal_mail_address) StrAllocCopy(cc_address, personal_mail_address); if (!header_prompt("Cc", &cc_address, LINESIZE)) { goto cancelled; } comma_append(&ccaddr, cc_address); } #if !USE_VMS_MAILER HTSprintf(&header, "%s: %s\n", label, the_subject); #if !CAN_PIPE_TO_MAILER if (*to_address) { HTSprintf(&header, "To: %s\n", to_address); } #endif /* ** Add the Cc: header. - FM */ if (!isEmpty(ccaddr)) { HTSprintf(&header, "Cc: %s\n", ccaddr); } /* ** Add the Keywords: header. - FM */ if (!isEmpty(keywords)) { HTSprintf(&header, "Keywords: %s\n", keywords); } /* * Terminate the header. */ StrAllocCat(header, "\n"); CTRACE((tfp,"**header==\n%s",header)); #endif /* !VMS */ if (!no_editor && !isEmpty(editor)) { if (body) { cp1 = body; while((cp = strchr(cp1, '\n')) != NULL) { *cp++ = '\0'; fprintf(fd, "%s\n", cp1); cp1 = cp; } } else if (strcmp(HTLoadedDocumentURL(), "")) { /* * Ask if the user wants to include the original message. */ BOOLEAN is_preparsed = (BOOL) (LYPreparsedSource && HTisDocumentSource()); if (HTConfirm(is_preparsed ? INC_PREPARSED_MSG_PROMPT : INC_ORIG_MSG_PROMPT) == YES) { print_wwwfile_to_fd(fd, (BOOL) !is_preparsed); } } LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ if (term_letter || LYCharIsINTERRUPT(c)) goto cleanup; /* * Spawn the users editor on the mail file */ edit_temporary_file(my_tmpfile, "", SPAWNING_EDITOR_FOR_MAIL); } else if (body) { /* * Let user review the body. - FM */ LYclear(); LYmove(0,0); LYaddstr(REVIEW_MESSAGE_BODY); LYrefresh(); cp1 = body; i = (LYlines - 5); while((cp = strchr(cp1, '\n')) != NULL) { if (i <= 0) { LYaddstr(RETURN_TO_CONTINUE); LYrefresh(); c = LYgetch(); LYaddstr("\n"); if (term_letter || LYCharIsINTERRUPT(c)) { goto cancelled; } i = (LYlines - 2); } *cp++ = '\0'; fprintf(fd, "%s\n", cp1); LYaddstr(cp1); LYaddstr("\n"); cp1 = cp; i--; } while (i >= 0) { LYaddstr("\n"); i--; } LYrefresh(); LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ } else { /* * Use the internal line editor for the message. */ LYaddstr(ENTER_MESSAGE_BELOW); LYaddstr(ENTER_PERIOD_WHEN_DONE_A); LYaddstr(ENTER_PERIOD_WHEN_DONE_B); LYaddstr("\n\n"); LYrefresh(); *user_input = '\0'; if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 || term_letter || STREQ(user_input, ".")) { goto cancelled; } while (!STREQ(user_input, ".") && !term_letter) { LYaddstr("\n"); remove_tildes(user_input); fprintf(fd, "%s\n", user_input); *user_input = '\0'; if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0) { goto cancelled; } } fprintf(fd, "\n"); /* Terminate the message. */ LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ } #if !USE_VMS_MAILER /* * Ignore CTRL-C on this last question. */ signal(SIGINT, SIG_IGN); #endif /* !VMS */ LYStatusLine = (LYlines - 1); c = HTConfirm (body ? SEND_MESSAGE_PROMPT : SEND_COMMENT_PROMPT); LYStatusLine = -1; if (c != YES) { LYclear(); /* clear the screen */ goto cleanup; } if ((body == NULL && LynxSigFile != NULL) && (fp = fopen(LynxSigFile, TXT_R)) != NULL) { LYStatusLine = (LYlines - 1); if (term_letter) { _user_message(APPEND_SIG_FILE, LynxSigFile); c = 0; } else { char *msg = NULL; HTSprintf0(&msg, APPEND_SIG_FILE, LynxSigFile); c = HTConfirm(msg); FREE(msg); } LYStatusLine = -1; if (c == YES) { if ((fd = fopen(my_tmpfile, TXT_A)) != NULL) { char *buffer = NULL; fputs("-- \n", fd); while (LYSafeGets(&buffer, fp) != NULL) { fputs(buffer, fd); } LYCloseOutput(fd); FREE(buffer); } } LYCloseInput(fp); } LYclear(); /* Clear the screen. */ /* * Send the message. */ #if USE_VMS_MAILER /* * Set the mail command. - FM */ if (isPMDF) { /* * For PMDF, put any keywords and the subject * in the header file and close it. - FM */ if (!isEmpty(keywords)) { fprintf(hfd, "Keywords: %s\n", keywords); } fprintf(hfd, "Subject: %s\n\n", the_subject); LYCloseTempFP(hfd); /* * Now set up the command. - FM */ HTSprintf0(&command, "%s %s %s,%s ", system_mail, system_mail_flags, hdrfile, my_tmpfile); } else { /* * For "generic" VMS MAIL, include the subject in the * command, and ignore any keywords to minimize risk * of them making the line too long or having problem * characters. - FM */ HTSprintf0(&command, "%s %s%s/subject=\"%s\" %s ", system_mail, system_mail_flags, (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"), the_subject, my_tmpfile); } vms_append_addrs(&command, to_address, ""); if (!isEmpty(ccaddr)) { vms_append_addrs(&command, ccaddr, "/CC"); } stop_curses(); printf("%s\n\n$ %s\n\n%s", SENDING_COMMENT, command, PLEASE_WAIT); LYSystem(command); /* SENDING COMMENT (VMS) */ FREE(command); LYSleepAlert(); start_curses(); #else /* Unix/DOS/Windows */ /* * Send the tmpfile into sendmail. */ _statusline(SENDING_YOUR_MSG); #if CAN_PIPE_TO_MAILER signal(SIGINT, SIG_IGN); if ((fp = LYPipeToMailer()) == 0) { HTInfoMsg(CANCELLED); } #else if ((fp = LYOpenTemp(tmpfile2, ".txt", "w")) == NULL) { HTAlert(MAILTO_URL_TEMPOPEN_FAILED); } #endif /* CAN_PIPE_TO_MAILER */ if (fp != 0) { fd = fopen(my_tmpfile, TXT_R); if (fd == NULL) { HTInfoMsg(CANCELLED); #if CAN_PIPE_TO_MAILER pclose(fp); #else LYCloseTempFP(fp); #endif /* CAN_PIPE_TO_MAILER */ } else { #if USE_BLAT_MAILER if (!mail_is_blat) fputs(header, fp); #else fputs(header, fp); #endif while ((n = fread(buf, 1, sizeof(buf), fd)) != 0) { fwrite(buf, 1, n, fp); } #if CAN_PIPE_TO_MAILER pclose(fp); #else LYCloseTempFP(fp); /* Close the tmpfile. */ LYSendMailFile ( to_address, tmpfile2, the_subject, ccaddr, SENDING_COMMENT); LYRemoveTemp(tmpfile2); /* Delete the tmpfile. */ #endif /* CAN_PIPE_TO_MAILER */ LYCloseInput(fd); /* Close the tmpfile. */ } } #endif /* USE_VMS_MAILER */ goto cleanup; /* * Come here to cleanup and exit. */ cancelled: HTInfoMsg(CANCELLED); LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ cleanup: signal(SIGINT, cleanup_sig); term_letter = FALSE; #if USE_VMS_MAILER while (LYRemoveTemp(my_tmpfile) == 0) ; /* Delete the tmpfile(s). */ if (isPMDF) { LYRemoveTemp(hdrfile); /* Delete the hdrfile. */ } #else FREE(header); LYRemoveTemp(my_tmpfile); /* Delete the tmpfile. */ #endif /* VMS */ FREE(from_address); FREE(the_subject); FREE(cc_address); FREE(to_address); FREE(ccaddr); FREE(keywords); FREE(body); return; }
/* ** Canonicalizes the URL in the following manner starting from the host ** pointer: ** ** 1) The host name is converted to lowercase ** 2) Chop off port if `:80' (http), `:70' (gopher), or `:21' (ftp) ** ** Return: OK The position of the current path part of the URL ** which might be the old one or a new one. */ PRIVATE char * HTCanon (char ** filename, char * host) { char *newname = NULL; char *port; char *strptr; char *path; char *access = host-3; while (access>*filename && *(access-1)!='/') /* Find access method */ access--; if ((path = strchr(host, '/')) == NULL) /* Find path */ path = host + strlen(host); if ((strptr = strchr(host, '@')) != NULL && strptr<path) /* UserId */ host = strptr; if ((port = strchr(host, ':')) != NULL && port>path) /* Port number */ port = NULL; strptr = host; /* Convert to lower-case */ while (strptr<path) { *strptr = TOLOWER(*strptr); strptr++; } /* Does the URL contain a full domain name? This also works for a numerical host name. The domain name is already made lower-case and without a trailing dot. */ #if 0 if (((strptr = strchr(host, '.')) == NULL || strptr >= path) && strncasecomp(host, "localhost", 9)) { const char *domain = HTGetDomainName(); if (domain && *domain) { if ((newname = (char *) HT_CALLOC(1, strlen(*filename) + strlen(domain)+2)) == NULL) HT_OUTOFMEM("HTCanon"); if (port) strncpy(newname, *filename, (int) (port-*filename)); else strncpy(newname, *filename, (int) (path-*filename)); strcat(newname, "."); strcat(newname, domain); } } else /* Look for a trailing dot */ #endif { char *dot = port ? port : path; if (dot > *filename && *--dot=='.') { char *orig=dot, *dest=dot+1; while((*orig++ = *dest++)); if (port) port--; path--; } } /* Chop off port if `:', `:80' (http), `:70' (gopher), or `:21' (ftp) */ if (port) { if (!*(port+1) || *(port+1)=='/') { if (!newname) { char *orig=port, *dest=port+1; while((*orig++ = *dest++)); } } else if ((!strncmp(access, "http", 4) && (*(port+1)=='8'&&*(port+2)=='0'&&(*(port+3)=='/'||!*(port+3)))) || (!strncmp(access, "gopher", 6) && (*(port+1)=='7'&&*(port+2)=='0'&&(*(port+3)=='/'||!*(port+3)))) || (!strncmp(access, "ftp", 3) && (*(port+1)=='2'&&*(port+2)=='1'&&(*(port+3)=='/'||!*(port+3))))) { if (!newname) { char *orig=port, *dest=port+3; while((*orig++ = *dest++)); path -= 3; /* Update path position, Henry Minsky */ } } else if (newname) strncat(newname, port, (int) (path-port)); } if (newname) { char *newpath = newname+strlen(newname); strcat(newname, path); path = newpath; HT_FREE(*filename); /* Free old copy */ *filename = newname; } return path; }
void LYDownload(char *line) { char *Line = NULL, *method, *file, *sug_file = NULL; int method_number; int count; char *the_command = 0; bstring *buffer = NULL; bstring *command = NULL; char *cp; lynx_list_item_type *download_command = 0; int ch; RecallType recall; int FnameTotal; int FnameNum; BOOLEAN FirstRecall = TRUE; BOOLEAN SecondS = FALSE; #ifdef VMS LYDidRename = FALSE; #endif /* VMS */ /* * Make sure we have a valid download file comparison string loaded via the * download options menu. - FM */ if (LYValidDownloadFile[0] == '\0') { goto failed; } /* * Make a copy of the LYNXDOWNLOAD internal URL for parsing. - FM */ StrAllocCopy(Line, line); /* * Parse out the File, sug_file, and the Method. */ if ((file = strstr(Line, "/File=")) == NULL) goto failed; *file = '\0'; /* * Go past "File=". */ file += 6; if ((sug_file = strstr(file + 1, "/SugFile=")) != NULL) { *sug_file = '\0'; /* * Go past "SugFile=". */ sug_file += 9; HTUnEscape(sug_file); } /* * Make sure that the file string is the one from the last displayed * download options menu. - FM */ if (strcmp(file, LYValidDownloadFile)) { goto failed; } #if defined(DIRED_SUPPORT) /* FIXME: use HTLocalName */ if (!StrNCmp(file, "file://localhost", 16)) { #ifdef __DJGPP__ if (!StrNCmp(file + 16, "/dev/", 5)) file += 16; else { file += 17; file = HTDOS_name(file); } #else file += 16; #endif /* __DJGPP__ */ } else if (isFILE_URL(file)) file += LEN_FILE_URL; HTUnEscape(file); #else #if defined(_WINDOWS) /* 1997/10/15 (Wed) 16:27:38 */ if (!StrNCmp(file, "file://localhost/", 17)) file += 17; else if (!StrNCmp(file, "file:/", 6)) file += 6; HTUnEscape(file); #endif /* _WINDOWS */ #endif /* DIRED_SUPPORT */ if ((method = strstr(Line, "Method=")) == NULL) goto failed; /* * Go past "Method=". */ method += 7; method_number = atoi(method); /* * Set up the sug_filenames recall buffer. */ FnameTotal = (sug_filenames ? HTList_count(sug_filenames) : 0); recall = ((FnameTotal >= 1) ? RECALL_URL : NORECALL); FnameNum = FnameTotal; if (method_number < 0) { /* * Write to local file. */ _statusline(FILENAME_PROMPT); retry: if (sug_file) { BStrCopy0(buffer, sug_file); } else { BStrCopy0(buffer, ""); } check_recall: if ((ch = LYgetBString(&buffer, FALSE, 0, recall)) < 0 || isBEmpty(buffer) || ch == UPARROW_KEY || ch == DNARROW_KEY) { if (recall && ch == UPARROW_KEY) { if (FirstRecall) { FirstRecall = FALSE; /* * Use the last Fname in the list. - FM */ FnameNum = 0; } else { /* * Go back to the previous Fname in the list. - FM */ FnameNum++; } if (FnameNum >= FnameTotal) { /* * Reset the FirstRecall flag, and use sug_file or a blank. * - FM */ FirstRecall = TRUE; FnameNum = FnameTotal; _statusline(FILENAME_PROMPT); goto retry; } else if ((cp = (char *) HTList_objectAt(sug_filenames, FnameNum)) != NULL) { BStrCopy0(buffer, cp); if (FnameTotal == 1) { _statusline(EDIT_THE_PREV_FILENAME); } else { _statusline(EDIT_A_PREV_FILENAME); } goto check_recall; } } else if (recall && ch == DNARROW_KEY) { if (FirstRecall) { FirstRecall = FALSE; /* * Use the first Fname in the list. - FM */ FnameNum = FnameTotal - 1; } else { /* * Advance to the next Fname in the list. - FM */ FnameNum--; } if (FnameNum < 0) { /* * Set the FirstRecall flag, and use sug_file or a blank. * - FM */ FirstRecall = TRUE; FnameNum = FnameTotal; _statusline(FILENAME_PROMPT); goto retry; } else if ((cp = (char *) HTList_objectAt(sug_filenames, FnameNum)) != NULL) { BStrCopy0(buffer, cp); if (FnameTotal == 1) { _statusline(EDIT_THE_PREV_FILENAME); } else { _statusline(EDIT_A_PREV_FILENAME); } goto check_recall; } } /* * Save cancelled. */ goto cancelled; } BStrCopy(command, buffer); if (!LYValidateFilename(&buffer, &command)) goto cancelled; #ifdef HAVE_POPEN else if (LYIsPipeCommand(buffer->str)) { /* I don't know how to download to a pipe */ HTAlert(CANNOT_WRITE_TO_FILE); _statusline(NEW_FILENAME_PROMPT); FirstRecall = TRUE; FnameNum = FnameTotal; goto retry; } #endif /* * See if it already exists. */ switch (LYValidateOutput(buffer->str)) { case 'Y': break; case 'N': _statusline(NEW_FILENAME_PROMPT); FirstRecall = TRUE; FnameNum = FnameTotal; goto retry; default: goto cleanup; } /* * See if we can write to it. */ CTRACE((tfp, "LYDownload: filename is %s\n", buffer->str)); SecondS = TRUE; HTInfoMsg(SAVING); #ifdef VMS /* * Try rename() first. - FM */ CTRACE((tfp, "command: rename(%s, %s)\n", file, buffer->str)); if (rename(file, buffer->str)) { /* * Failed. Use spawned COPY_COMMAND. - FM */ CTRACE((tfp, " FAILED!\n")); LYCopyFile(file, buffer->str); } else { /* * We don't have the temporary file (it was renamed to a permanent * file), so set a flag to pop out of the download menu. - FM */ LYDidRename = TRUE; } chmod(buffer->str, HIDE_CHMOD); #else /* Unix: */ LYCopyFile(file, buffer->str); LYRelaxFilePermissions(buffer->str); #endif /* VMS */ } else { /* * Use configured download commands. */ BStrCopy0(buffer, ""); for (count = 0, download_command = downloaders; count < method_number; count++, download_command = download_command->next) ; /* null body */ /* * Commands have the form "command %s [etc]" where %s is the filename. */ if (download_command->command != NULL) { /* * Check for two '%s' and ask for the local filename if there is. */ if (HTCountCommandArgs(download_command->command) >= 2) { _statusline(FILENAME_PROMPT); again: if (sug_file) { BStrCopy0(buffer, sug_file); } else { BStrCopy0(buffer, ""); } check_again: if ((ch = LYgetBString(&buffer, FALSE, 0, recall)) < 0 || isBEmpty(buffer) || ch == UPARROW_KEY || ch == DNARROW_KEY) { if (recall && ch == UPARROW_KEY) { if (FirstRecall) { FirstRecall = FALSE; /* * Use the last Fname in the list. - FM */ FnameNum = 0; } else { /* * Go back to the previous Fname in the list. - FM */ FnameNum++; } if (FnameNum >= FnameTotal) { /* * Reset the FirstRecall flag, and use sug_file or * a blank. - FM */ FirstRecall = TRUE; FnameNum = FnameTotal; _statusline(FILENAME_PROMPT); goto again; } else if ((cp = (char *) HTList_objectAt(sug_filenames, FnameNum)) != NULL) { BStrCopy0(buffer, cp); if (FnameTotal == 1) { _statusline(EDIT_THE_PREV_FILENAME); } else { _statusline(EDIT_A_PREV_FILENAME); } goto check_again; } } else if (recall && ch == DNARROW_KEY) { if (FirstRecall) { FirstRecall = FALSE; /* * Use the first Fname in the list. - FM */ FnameNum = FnameTotal - 1; } else { /* * Advance to the next Fname in the list. - FM */ FnameNum--; } if (FnameNum < 0) { /* * Set the FirstRecall flag, and use sug_file or a * blank. - FM */ FirstRecall = TRUE; FnameNum = FnameTotal; _statusline(FILENAME_PROMPT); goto again; } else if ((cp = (char *) HTList_objectAt(sug_filenames, FnameNum)) != NULL) { BStrCopy0(buffer, cp); if (FnameTotal == 1) { _statusline(EDIT_THE_PREV_FILENAME); } else { _statusline(EDIT_A_PREV_FILENAME); } goto check_again; } } /* * Download cancelled. */ goto cancelled; } if (no_dotfiles || !show_dotfiles) { if (*LYPathLeaf(buffer->str) == '.') { HTAlert(FILENAME_CANNOT_BE_DOT); _statusline(NEW_FILENAME_PROMPT); goto again; } } /* * Cancel if the user entered "/dev/null" on Unix, or an "nl:" * path on VMS. - FM */ if (LYIsNullDevice(buffer->str)) { goto cancelled; } SecondS = TRUE; } /* * The following is considered a bug by the community. If the * command only takes one argument on the command line, then the * suggested file name is not used. It actually is not a bug at * all and does as it should, putting both names on the command * line. */ count = 1; HTAddParam(&the_command, download_command->command, count, file); if (HTCountCommandArgs(download_command->command) > 1) HTAddParam(&the_command, download_command->command, ++count, buffer->str); HTEndParam(&the_command, download_command->command, count); } else { HTAlert(MISCONF_DOWNLOAD_COMMAND); goto failed; } CTRACE((tfp, "command: %s\n", the_command)); stop_curses(); LYSystem(the_command); FREE(the_command); start_curses(); /* don't remove(file); */ } if (SecondS == TRUE) { #ifdef VMS if (0 == strncasecomp(buffer->str, "sys$disk:", 9)) { if (0 == StrNCmp((buffer->str + 9), "[]", 2)) { HTAddSugFilename(buffer->str + 11); } else { HTAddSugFilename(buffer->str + 9); } } else { HTAddSugFilename(buffer->str); } #else HTAddSugFilename(buffer->str); #endif /* VMS */ } goto cleanup; failed: HTAlert(CANNOT_DOWNLOAD_FILE); goto cleanup; cancelled: HTInfoMsg(CANCELLING); cleanup: FREE(Line); BStrFree(buffer); return; }