New interface for URL parsing

git-svn-id: svn://10.0.0.236/trunk@31173 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rhp%netscape.com
1999-05-11 23:39:48 +00:00
parent 8b84000b7b
commit bcdda805fa
2 changed files with 985 additions and 0 deletions

View File

@@ -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 = "<B>", cite_close1 = "</B>";
break;
case MSG_ItalicFont:
cite_open1 = "<I>", cite_close1 = "</I>";
break;
case MSG_BoldItalicFont:
cite_open1 = "<B><I>", cite_close1 = "</I></B>";
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 = "<FONT SIZE=\"+1\">", cite_close2 = "</FONT>";
break;
case MSG_Smaller:
cite_open2 = "<FONT SIZE=\"-1\">", cite_close2 = "</FONT>";
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, "<FONT COLOR=");
output_ptr += PL_strlen(output_ptr);
PL_strcpy(output_ptr, color);
output_ptr += PL_strlen(output_ptr);
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,
"<A HREF=\"%s\">%s</A>",
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, "&lt;");
output_ptr += 4;
col++;
}
else if(*cp == '>')
{
PL_strcpy(output_ptr, "&gt;");
output_ptr += 4;
col++;
}
else if(*cp == '&')
{
PL_strcpy(output_ptr, "&amp;");
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, "</FONT>");
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 <IMG SRC="foo.gif"> in it,
but which has no <BASE> 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);
}

View File

@@ -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__ */