diff --git a/mozilla/mailnews/mime/src/nsMimeURLUtils.cpp b/mozilla/mailnews/mime/src/nsMimeURLUtils.cpp
new file mode 100644
index 00000000000..eaf522f0df0
--- /dev/null
+++ b/mozilla/mailnews/mime/src/nsMimeURLUtils.cpp
@@ -0,0 +1,931 @@
+/* -*- 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.
+ */
+#include "prtypes.h"
+#include "prmem.h"
+#include "plstr.h"
+#include "nsCRT.h"
+#include "nsMimeTransition.h"
+#ifndef XP_MAC
+ #include "nsTextFragment.h"
+#endif
+#include "msgCore.h"
+#include "mimebuf.h"
+#include "nsMimeURLUtils.h"
+
+nsMimeURLUtils::nsMimeURLUtils()
+{
+ /* the following macro is used to initialize the ref counting data */
+ NS_INIT_REFCNT();
+}
+
+nsMimeURLUtils::~nsMimeURLUtils()
+{
+}
+
+/* the following macros actually implement addref, release and query interface for our component. */
+NS_IMPL_ADDREF(nsMimeURLUtils)
+NS_IMPL_RELEASE(nsMimeURLUtils)
+NS_IMPL_QUERY_INTERFACE(nsMimeURLUtils, nsIMimeURLUtils::GetIID()); /* we need to pass in the interface ID of this interface */
+
+ /* this function will be used by the factory to generate an RFC-822 Parser....*/
+nsresult NS_NewMimeURLUtils(nsIMimeURLUtils ** aInstancePtrResult)
+{
+ /* note this new macro for assertions...they can take a string describing the assertion */
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "nsnull ptr");
+ if (nsnull != aInstancePtrResult)
+ {
+ nsMimeURLUtils* utils = new nsMimeURLUtils();
+ if (utils)
+ return utils->QueryInterface(nsIMimeURLUtils::GetIID(), (void **)aInstancePtrResult);
+ else
+ return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
+ }
+ else
+ return NS_ERROR_NULL_POINTER; /* aInstancePtrResult was NULL....*/
+}
+
+/* from libnet/mkutils.c */
+nsresult
+nsMimeURLUtils::URLType(const char *URL, PRInt32 *retType)
+{
+ if (!URL || (URL && *URL == '\0'))
+ return(NS_ERROR_NULL_POINTER);
+
+ switch(*URL) {
+ case 'a':
+ case 'A':
+ if(!PL_strncasecmp(URL,"about:security", 14))
+ {
+ *retType = SECURITY_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"about:",6))
+ {
+ *retType = ABOUT_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'f':
+ case 'F':
+ if(!PL_strncasecmp(URL,"ftp:",4))
+ {
+ *retType = FTP_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"file:",5))
+ {
+ *retType = FILE_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'g':
+ case 'G':
+ if(!PL_strncasecmp(URL,"gopher:",7))
+ {
+ *retType = GOPHER_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'h':
+ case 'H':
+ if(!PL_strncasecmp(URL,"http:",5))
+ {
+ *retType = HTTP_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"https:",6))
+ {
+ *retType = SECURE_HTTP_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'i':
+ case 'I':
+ if(!PL_strncasecmp(URL,"internal-gopher-",16))
+ {
+ *retType = INTERNAL_IMAGE_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"internal-news-",14))
+ {
+ *retType = INTERNAL_IMAGE_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"internal-edit-",14))
+ {
+ *retType = INTERNAL_IMAGE_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"internal-attachment-",20))
+ {
+ *retType = INTERNAL_IMAGE_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"internal-dialog-handler",23))
+ {
+ *retType = HTML_DIALOG_HANDLER_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"internal-panel-handler",22))
+ {
+ *retType = HTML_PANEL_HANDLER_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"internal-security-",18))
+ {
+ *retType = INTERNAL_SECLIB_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"IMAP:",5))
+ {
+ *retType = IMAP_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'j':
+ case 'J':
+ if(!PL_strncasecmp(URL, "javascript:",11))
+ {
+ *retType = MOCHA_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'l':
+ case 'L':
+ if(!PL_strncasecmp(URL, "livescript:",11))
+ {
+ *retType = MOCHA_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'm':
+ case 'M':
+ if(!PL_strncasecmp(URL,"mailto:",7))
+ {
+ *retType = MAILTO_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"mailbox:",8))
+ {
+ *retType = MAILBOX_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL, "mocha:",6))
+ {
+ *retType = MOCHA_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if(!PL_strncasecmp(URL,"news:",5))
+ {
+ *retType = NEWS_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'p':
+ case 'P':
+ if(!PL_strncasecmp(URL,"pop3:",5))
+ {
+ *retType = POP3_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'r':
+ case 'R':
+ if(!PL_strncasecmp(URL,"rlogin:",7))
+ {
+ *retType = RLOGIN_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 's':
+ case 'S':
+ if(!PL_strncasecmp(URL,"snews:",6))
+ {
+ *retType = NEWS_TYPE_URL;
+ return NS_OK;
+ }
+ case 't':
+ case 'T':
+ if(!PL_strncasecmp(URL,"telnet:",7))
+ {
+ *retType = TELNET_TYPE_URL;
+ return NS_OK;
+ }
+ else if(!PL_strncasecmp(URL,"tn3270:",7))
+ {
+ *retType = TN3270_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'v':
+ case 'V':
+ if(!PL_strncasecmp(URL, VIEW_SOURCE_URL_PREFIX,
+ sizeof(VIEW_SOURCE_URL_PREFIX)-1))
+ {
+ *retType = VIEW_SOURCE_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'w':
+ case 'W':
+ if(!PL_strncasecmp(URL,"wais:",5))
+ {
+ *retType = WAIS_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+ case 'u':
+ case 'U':
+ if(!PL_strncasecmp(URL,"URN:",4))
+ {
+ *retType = URN_TYPE_URL;
+ return NS_OK;
+ }
+ break;
+
+ }
+
+ /* no type match :( */
+ *retType = 0;
+ return NS_OK;
+}
+
+nsresult
+nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size,
+ char *output, int output_size, PRBool urls_only)
+{
+ int col = 0;
+ const char *cp;
+ const char *end = input + input_size;
+ char *output_ptr = output;
+ char *end_of_buffer = output + output_size - 40; /* add safty zone :( */
+ PRBool line_is_citation = PR_FALSE;
+ const char *cite_open1, *cite_close1;
+ const char *cite_open2, *cite_close2;
+ const char* color = NULL;
+
+ if (urls_only)
+ {
+ cite_open1 = cite_close1 = "";
+ cite_open2 = cite_close2 = "";
+ }
+ else
+ {
+ cite_open1 = "", cite_close1 = "";
+ cite_open2 = cite_close2 = "";
+
+/********** RICHIE_CITATION
+ MSG_Prefs* prefs;
+ MSG_FONT font = MSG_ItalicFont;
+ MSG_CITATION_SIZE size = MSG_NormalSize;
+
+ if (pane) {
+ prefs = MSG_GetPrefs(pane);
+ MSG_GetCitationStyle(prefs, &font, &size, &color);
+ }
+ switch (font)
+ {
+ case MSG_PlainFont:
+ cite_open1 = "", cite_close1 = "";
+ break;
+ case MSG_BoldFont:
+ cite_open1 = "", cite_close1 = "";
+ break;
+ case MSG_ItalicFont:
+ cite_open1 = "", cite_close1 = "";
+ break;
+ case MSG_BoldItalicFont:
+ cite_open1 = "", cite_close1 = "";
+ break;
+ default:
+ PR_ASSERT(0);
+ cite_open1 = cite_close1 = "";
+ break;
+ }
+
+ switch (size)
+ {
+ case MSG_NormalSize:
+ cite_open2 = "", cite_close2 = "";
+ break;
+ case MSG_Bigger:
+ cite_open2 = "", cite_close2 = "";
+ break;
+ case MSG_Smaller:
+ cite_open2 = "", cite_close2 = "";
+ break;
+ default:
+ PR_ASSERT(0);
+ cite_open2 = cite_close2 = "";
+ break;
+ }
+**********************/
+ }
+
+ if (!urls_only)
+ {
+ /* Decide whether this line is a quotation, and should be italicized.
+ This implements the following case-sensitive regular expression:
+
+ ^[ \t]*[A-Z]*[]>]
+
+ Which matches these lines:
+
+ > blah blah blah
+ > blah blah blah
+ LOSER> blah blah blah
+ LOSER] blah blah blah
+ */
+ const char *s = input;
+ while (s < end && IS_SPACE (*s)) s++;
+ while (s < end && *s >= 'A' && *s <= 'Z') s++;
+
+ if (s >= end)
+ ;
+ else if (input_size >= 6 && *s == '>' &&
+ !PL_strncmp (input, ">From ", 6)) /* #$%^ing sendmail... */
+ ;
+ else if (*s == '>' || *s == ']')
+ {
+ line_is_citation = PR_TRUE;
+ PL_strcpy(output_ptr, cite_open1);
+ output_ptr += PL_strlen(cite_open1);
+ PL_strcpy(output_ptr, cite_open2);
+ output_ptr += PL_strlen(cite_open2);
+ if (color &&
+ output_ptr + PL_strlen(color) + 20 < end_of_buffer) {
+ PL_strcpy(output_ptr, "");
+ output_ptr += PL_strlen(output_ptr);
+ }
+ }
+ }
+
+ /* Normal lines are scanned for buried references to URL's
+ Unfortunately, it may screw up once in a while (nobody's perfect)
+ */
+ for(cp = input; cp < end && output_ptr < end_of_buffer; cp++)
+ {
+ /* if URLType returns true then it is most likely a URL
+ But only match protocol names if at the very beginning of
+ the string, or if the preceeding character was not alphanumeric;
+ this lets us match inside "---HTTP://XXX" but not inside of
+ things like "NotHTTP://xxx"
+ */
+ int type = 0;
+ URLType(cp, &type);
+ if(!IS_SPACE(*cp) &&
+ (cp == input || (!IS_ALPHA(cp[-1]) && !IS_DIGIT(cp[-1]))) &&
+ (type) != 0)
+ {
+ const char *cp2;
+ for(cp2=cp; cp2 < end; cp2++)
+ {
+ /* These characters always mark the end of the URL. */
+ if (IS_SPACE(*cp2) ||
+ *cp2 == '<' || *cp2 == '>' ||
+ *cp2 == '`' || *cp2 == ')' ||
+ *cp2 == '\'' || *cp2 == '"' ||
+ *cp2 == ']' || *cp2 == '}'
+ )
+ break;
+
+ }
+
+ /* Check for certain punctuation characters on the end, and strip
+ them off. */
+ while (cp2 > cp &&
+ (cp2[-1] == '.' || cp2[-1] == ',' || cp2[-1] == '!' ||
+ cp2[-1] == ';' || cp2[-1] == '-' || cp2[-1] == '?' ||
+ cp2[-1] == '#'))
+ cp2--;
+
+ col += (cp2 - cp);
+
+ /* if the url is less than 7 characters then we screwed up
+ * and got a "news:" url or something which is worthless
+ * to us. Exclude the A tag in this case.
+ *
+ * Also exclude any URL that ends in a colon; those tend
+ * to be internal and magic and uninteresting.
+ *
+ * And also exclude the builtin icons, whose URLs look
+ * like "internal-gopher-binary".
+ */
+ if (cp2-cp < 7 ||
+ (cp2 > cp && cp2[-1] == ':') ||
+ !PL_strncmp(cp, "internal-", 9))
+ {
+ nsCRT::memcpy(output_ptr, cp, cp2-cp);
+ output_ptr += (cp2-cp);
+ *output_ptr = 0;
+ }
+ else
+ {
+ char *quoted_url;
+ PRInt32 size_left = output_size - (output_ptr-output);
+
+ if(cp2-cp > size_left)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCRT::memcpy(output_ptr, cp, cp2-cp);
+ output_ptr[cp2-cp] = 0;
+ quoted_url = nsEscapeHTML(output_ptr);
+ if (!quoted_url) return NS_ERROR_OUT_OF_MEMORY;
+ PR_snprintf(output_ptr, size_left,
+ "%s",
+ quoted_url,
+ quoted_url);
+ output_ptr += PL_strlen(output_ptr);
+ PR_Free(quoted_url);
+ output_ptr += PL_strlen(output_ptr);
+ }
+
+ cp = cp2-1; /* go to next word */
+ }
+ else
+ {
+ /* Make sure that special symbols don't screw up the HTML parser
+ */
+ if(*cp == '<')
+ {
+ PL_strcpy(output_ptr, "<");
+ output_ptr += 4;
+ col++;
+ }
+ else if(*cp == '>')
+ {
+ PL_strcpy(output_ptr, ">");
+ output_ptr += 4;
+ col++;
+ }
+ else if(*cp == '&')
+ {
+ PL_strcpy(output_ptr, "&");
+ output_ptr += 5;
+ col++;
+ }
+ else
+ {
+ *output_ptr++ = *cp;
+ col++;
+ }
+ }
+ }
+
+ *output_ptr = 0;
+
+ if (line_is_citation) /* Close off the highlighting */
+ {
+ if (color) {
+ PL_strcpy(output_ptr, "");
+ output_ptr += PL_strlen(output_ptr);
+ }
+
+ PL_strcpy(output_ptr, cite_close2);
+ output_ptr += PL_strlen (cite_close2);
+ PL_strcpy(output_ptr, cite_close1);
+ output_ptr += PL_strlen (cite_close1);
+ }
+
+ return NS_OK;
+}
+
+/* modifies a url of the form /foo/../foo1 -> /foo1
+ *
+ * it only operates on "file" "ftp" and "http" url's all others are returned
+ * unmodified
+ *
+ * returns the modified passed in URL string
+ */
+nsresult
+nsMimeURLUtils::ReduceURL (char *url, char **retURL)
+{
+ PRInt32 url_type;
+
+ URLType(url, &url_type);
+ char * fwd_ptr;
+ char * url_ptr;
+ char * path_ptr;
+
+ if(!url)
+ {
+ *retURL = url;
+ return NS_OK;
+ }
+
+ if(url_type == HTTP_TYPE_URL || url_type == FILE_TYPE_URL ||
+ url_type == FTP_TYPE_URL ||
+ url_type == SECURE_HTTP_TYPE_URL)
+ {
+
+ /* find the path so we only change that and not the host
+ */
+ path_ptr = PL_strchr(url, '/');
+
+ if(!path_ptr)
+ {
+ *retURL = url;
+ return NS_OK;
+ }
+
+ if(*(path_ptr+1) == '/')
+ path_ptr = PL_strchr(path_ptr+2, '/');
+
+ if(!path_ptr)
+ {
+ *retURL = url;
+ return NS_OK;
+ }
+
+ fwd_ptr = path_ptr;
+ url_ptr = path_ptr;
+
+ for(; *fwd_ptr != '\0'; fwd_ptr++)
+ {
+
+ if(*fwd_ptr == '/' && *(fwd_ptr+1) == '.' && *(fwd_ptr+2) == '/')
+ {
+ /* remove ./
+ */
+ fwd_ptr += 1;
+ }
+ else if(*fwd_ptr == '/' && *(fwd_ptr+1) == '.' && *(fwd_ptr+2) == '.' &&
+ (*(fwd_ptr+3) == '/' || *(fwd_ptr+3) == '\0'))
+ {
+ /* remove foo/..
+ */
+ /* reverse the url_ptr to the previous slash
+ */
+ if(url_ptr != path_ptr)
+ url_ptr--; /* we must be going back at least one */
+ for(;*url_ptr != '/' && url_ptr != path_ptr; url_ptr--)
+ ; /* null body */
+
+ /* forward the fwd_prt past the ../
+ */
+ fwd_ptr += 2;
+ }
+ else
+ {
+ /* copy the url incrementaly
+ */
+ *url_ptr++ = *fwd_ptr;
+ }
+ }
+ *url_ptr = '\0'; /* terminate the url */
+ }
+
+ *retURL = url;
+ return NS_OK;
+}
+
+/*
+ * Makes a relative URL into an absolute one.
+ *
+ * If an absolute url is passed in it will be copied and returned.
+ *
+ * Always returns a malloc'd string or NULL on out of memory error
+ */
+nsresult
+nsMimeURLUtils::MakeAbsoluteURL(char * absolute_url, char * relative_url, char **retURL)
+{
+ char * ret_url=0;
+ int new_length;
+ char * cat_point=0;
+ char cat_point_char;
+ int url_type=0;
+ int base_type;
+
+ /* if either is NULL
+ */
+ if(!absolute_url || !relative_url)
+ {
+ mime_SACopy(&ret_url, relative_url);
+ *retURL = ret_url;
+ return NS_OK;
+ }
+
+ /* use the URLType function to figure
+ * out if it's a recognized URL method
+ */
+ URLType(relative_url, &url_type);
+
+ /* there are some extra cases we need to catch
+ */
+ if(!url_type)
+ {
+ switch(*relative_url)
+ {
+ case 'i':
+ if(!PL_strncmp(relative_url,"internal-icon-", 14)
+ || !PL_strncmp(relative_url,"internal-external-reconnect:", 28)
+ || !PL_strcmp(relative_url,"internal-external-plugin"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ break;
+ case '/':
+ if(!PL_strncasecmp(relative_url, "/mc-icons/", 10) ||
+ !PL_strncasecmp(relative_url, "/ns-icons/", 10))
+ {
+ if(!PL_strcmp(relative_url+10, "menu.gif"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ else if(!PL_strcmp(relative_url+10, "unknown.gif"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ else if(!PL_strcmp(relative_url+10, "text.gif"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ else if(!PL_strcmp(relative_url+10, "image.gif"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ else if(!PL_strcmp(relative_url+10, "sound.gif"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ else if(!PL_strcmp(relative_url+10, "binary.gif"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ else if(!PL_strcmp(relative_url+10, "movie.gif"))
+ url_type = INTERNAL_IMAGE_TYPE_URL;
+ }
+ break;
+ }
+ }
+ else if(url_type == ABOUT_TYPE_URL)
+ {
+ /* don't allow about:cache in a document */
+ if(!PL_strncasecmp(relative_url, "about:cache", 11)
+ || !PL_strncasecmp(relative_url, "about:global", 12)
+ || !PL_strncasecmp(relative_url, "about:image-cache", 17)
+ || !PL_strncasecmp(relative_url, "about:memory-cache", 18))
+ {
+ *retURL = PL_strdup("");
+ return NS_OK;
+ }
+ }
+
+ // RICHIE - NO LONGER APPLICABLE
+ // if(!url_type)
+ // url_type = net_CheckForExternalURLType(relative_url);
+
+ if(url_type)
+ {
+ /* it's either an absolute url
+ * or a messed up one of the type proto:/path
+ * but notice the missing host.
+ */
+ char * colon = PL_strchr(relative_url, ':'); /* must be there */
+
+ if( (colon && *(colon+1) == '/' && *(colon+2) == '/') ||
+ (url_type != GOPHER_TYPE_URL
+ && url_type != FTP_TYPE_URL
+ && url_type != HTTP_TYPE_URL
+ && url_type != SECURE_HTTP_TYPE_URL
+ && url_type != RLOGIN_TYPE_URL
+ && url_type != TELNET_TYPE_URL
+ && url_type != TN3270_TYPE_URL
+ && url_type != WAIS_TYPE_URL) )
+ {
+ /* it appears to have all it's parts. Assume it's completely
+ * absolute
+ */
+ mime_SACopy(&ret_url, relative_url);
+ *retURL = ret_url;
+ return NS_OK;
+ }
+ else
+ {
+ /* it's a screwed up relative url of the form http:[relative url]
+ * remove the stuff before and at the colon and treat it as a normal
+ * relative url
+ */
+ char * colon = PL_strchr(relative_url, ':');
+
+ relative_url = colon+1;
+ }
+ }
+
+
+ /* At this point, we know that `relative_url' is not absolute.
+ If the base URL, `absolute_url', is a "mailbox:" URL, then
+ we should not allow relative expansion: that is,
+ NET_MakeAbsoluteURL("mailbox:/A/B/C", "YYY") should not
+ return "mailbox:/A/B/YYY".
+
+ However, expansion of "#" and "?" parameters should work:
+ NET_MakeAbsoluteURL("mailbox:/A/B/C?id=XXX", "#part2")
+ should be allowed to expand to "mailbox:/A/B/C?id=XXX#part2".
+
+ If you allow random HREFs in attached HTML to mail messages to
+ expand to mailbox URLs, then bad things happen -- among other
+ things, an entry will be automatically created in the folders
+ list for each of these bogus non-files.
+
+ It's an open question as to whether relative expansion should
+ be allowed for news: and snews: URLs.
+
+ Reasons to allow it:
+
+ = ClariNet has been using it
+
+ = (Their reason:) it's the only way for an HTML news message
+ to refer to another HTML news message in a way which
+ doesn't make assumptions about the name of the news host,
+ and which also doesn't assume that the message is on the
+ default news host.
+
+ Reasons to disallow it:
+
+ = Consistency with "mailbox:"
+
+ = If there is a news message which has type text/html, and
+ which has a relative URL like
in it,
+ but which has no tag, then we would expand that
+ image to "news:foo.gif". Which would fail, of course,
+ but which might annoy news admins by generating bogus
+ references.
+
+ So for now, let's allow
+ NET_MakeAbsoluteURL("news:123@4", "456@7") => "news:456@7"; and
+ NET_MakeAbsoluteURL("news://h/123@4", "456@7") => "news://h/456@7".
+ */
+ URLType(absolute_url, &base_type);
+ if ((base_type == MAILBOX_TYPE_URL || base_type == IMAP_TYPE_URL) &&
+ *relative_url != '#' &&
+ *relative_url != '?')
+ {
+ *retURL = PL_strdup("");
+ return NS_OK;
+ }
+
+ if(relative_url[0] == '/' && relative_url[1] == '/')
+ {
+ /* a host absolute URL
+ */
+
+ /* find the colon after the protocol
+ */
+ cat_point = PL_strchr(absolute_url, ':');
+ if (cat_point && base_type == WYSIWYG_TYPE_URL)
+ cat_point = PL_strchr(cat_point + 1, ':');
+
+ /* append after the colon
+ */
+ if(cat_point)
+ cat_point++;
+
+ }
+ else if(relative_url[0] == '/')
+ {
+ /* a path absolute URL
+ * append at the slash after the host part
+ */
+
+ /* find the colon after the protocol
+ */
+ char *colon = PL_strchr(absolute_url, ':');
+ if (colon && base_type == WYSIWYG_TYPE_URL)
+ colon = PL_strchr(colon + 1, ':');
+
+ if(colon)
+ {
+ if(colon[1] == '/' && colon[2] == '/')
+ {
+ /* find the next slash
+ */
+ cat_point = PL_strchr(colon+3, '/');
+
+ if(!cat_point)
+ {
+ /* if there isn't another slash then the cat point is the very end
+ */
+ cat_point = &absolute_url[PL_strlen(absolute_url)];
+ }
+ }
+ else
+ {
+ /* no host was given so the cat_point is right after the colon
+ */
+ cat_point = colon+1;
+ }
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ /* this will allow drive letters to work right on windows
+ */
+ if(IS_ALPHA(*cat_point) && *(cat_point+1) == ':')
+ cat_point += 2;
+#endif /* XP_WIN */
+
+ }
+ }
+ else if(relative_url[0] == '#')
+ {
+ /* a positioning within the same document relative url
+ *
+ * add teh relative url to the full text of the absolute url minus
+ * any # punctuation the url might have
+ *
+ */
+ char * hash = PL_strchr(absolute_url, '#');
+
+ if(hash)
+ {
+ char * ques_mark = PL_strchr(absolute_url, '?');
+
+ if(ques_mark)
+ {
+ /* this is a hack.
+ * copy things to try and make them more correct
+ */
+ *hash = '\0';
+
+ mime_SACopy(&ret_url, absolute_url);
+ mime_SACat(&ret_url, relative_url);
+ mime_SACat(&ret_url, ques_mark);
+
+ *hash = '#';
+
+ return(ReduceURL(ret_url, retURL));
+ }
+
+ cat_point = hash;
+ }
+ else
+ {
+ cat_point = &absolute_url[PL_strlen(absolute_url)]; /* the end of the URL */
+ }
+ }
+ else
+ {
+ /* a completely relative URL
+ *
+ * append after the last slash
+ */
+ char * ques = PL_strchr(absolute_url, '?');
+ char * hash = PL_strchr(absolute_url, '#');
+
+ if(ques)
+ *ques = '\0';
+
+ if(hash)
+ *hash = '\0';
+
+ cat_point = PL_strrchr(absolute_url, '/');
+
+ /* if there are no slashes then append right after the colon after the protocol
+ */
+ if(!cat_point)
+ cat_point = PL_strchr(absolute_url, ':');
+
+ /* set the value back
+ */
+ if(ques)
+ *ques = '?';
+
+ if(hash)
+ *hash = '#';
+
+ if(cat_point)
+ cat_point++; /* append right after the slash or colon not on it */
+ }
+
+ if(cat_point)
+ {
+ cat_point_char = *cat_point; /* save the value */
+ *cat_point = '\0';
+ new_length = PL_strlen(absolute_url) + PL_strlen(relative_url) + 1;
+ ret_url = (char *) PR_MALLOC(new_length);
+ if(!ret_url)
+ {
+ *retURL = NULL;
+ return NS_ERROR_OUT_OF_MEMORY; /* out of memory */
+ }
+
+ PL_strcpy(ret_url, absolute_url);
+ PL_strcat(ret_url, relative_url);
+ *cat_point = cat_point_char; /* set the absolute url back to its original state */
+ }
+ else
+ {
+ /* something went wrong. just return a copy of the relative url
+ */
+ mime_SACopy(&ret_url, relative_url);
+ }
+
+ return ReduceURL(ret_url, retURL);
+}
diff --git a/mozilla/mailnews/mime/src/nsMimeURLUtils.h b/mozilla/mailnews/mime/src/nsMimeURLUtils.h
new file mode 100644
index 00000000000..a319de22ff9
--- /dev/null
+++ b/mozilla/mailnews/mime/src/nsMimeURLUtils.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; 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.
+ */
+
+/********************************************************************************************************
+
+ Wrapper class for various parsing URL parsing routines...
+
+*********************************************************************************************************/
+
+#ifndef _nsMimeURLUtils_h__
+#define _nsMimeURLUtils_h__
+
+#include "nsIMimeURLUtils.h"
+
+class nsMimeURLUtils: public nsIMimeURLUtils {
+public:
+ nsMimeURLUtils();
+ virtual ~nsMimeURLUtils();
+
+ /* this macro defines QueryInterface, AddRef and Release for this class */
+ NS_DECL_ISUPPORTS
+
+ static const nsIID& IID(void) { static nsIID iid = NS_IMIME_URLUTILS_IID; return iid; }
+
+ NS_IMETHOD URLType(const char *URL, PRInt32 *retType);
+
+ NS_IMETHOD ReduceURL (char *url, char **retURL);
+
+ NS_IMETHOD ScanForURLs(const char *input, int32 input_size,
+ char *output, int output_size, PRBool urls_only);
+
+ NS_IMETHOD MakeAbsoluteURL(char * absolute_url, char * relative_url, char **retURL);
+};
+
+
+/* this function will be used by the factory to generate an RFC-822 Parser....*/
+extern nsresult NS_NewMimeURLUtils(nsIMimeURLUtils ** aInstancePtrResult);
+
+#endif /* _nsMimeURLUtils_h__ */