diff --git a/mailnews/mime/src/nsMimeURLUtils.cpp b/mailnews/mime/src/nsMimeURLUtils.cpp index 88f82867aee4..61884058aeb8 100644 --- a/mailnews/mime/src/nsMimeURLUtils.cpp +++ b/mailnews/mime/src/nsMimeURLUtils.cpp @@ -59,6 +59,64 @@ nsMimeURLUtils::~nsMimeURLUtils() { } +char * +FindAmbitiousMailToTag(const char *line) +{ + char *atLoc; + char *workLine; + + // Sanity... + if ( (!line) || (!*line) ) + return NULL; + + // Should I bother at all... + if ( !(atLoc = PL_strchr(line, '@')) ) + return NULL; + + // create a working copy... + workLine = PL_strdup(line); + if (!workLine) + return NULL; + + char *ptr = PL_strchr(workLine, '@'); + if (!ptr) + return NULL; + + *(ptr+1) = '\0'; + --ptr; + while (ptr >= workLine) + { + if (IS_SPACE(*ptr) || + *ptr == '<' || *ptr == '>' || + *ptr == '`' || *ptr == ')' || + *ptr == '\'' || *ptr == '"' || + *ptr == ']' || *ptr == '}' + ) + break; + --ptr; + } + + ++ptr; + + if ( (*ptr == '@') || (!PL_strncasecmp(ptr, "mailto:", 7)) ) + return NULL; + else + return (PL_strdup(ptr)); +} + +nsresult +AmbitiousURLType(const char *URL, PRInt32 *retType, const char *newURLTag) +{ + *retType = 0; + + if (!PL_strncasecmp(URL,newURLTag, PL_strlen(newURLTag))) + { + *retType = MAILTO_TYPE_URL; + } + + return NS_OK; +} + /* from libnet/mkutils.c */ nsresult nsMimeURLUtils::URLType(const char *URL, PRInt32 *retType) @@ -82,7 +140,8 @@ nsMimeURLUtils::URLType(const char *URL, PRInt32 *retType) break; case 'f': case 'F': - if(!PL_strncasecmp(URL,"ftp:",4)) + if ( (!PL_strncasecmp(URL,"ftp:",4)) || + (!PL_strncasecmp(URL,"ftp.",4)) ) { *retType = FTP_TYPE_URL; return NS_OK; @@ -251,6 +310,11 @@ nsMimeURLUtils::URLType(const char *URL, PRInt32 *retType) *retType = WAIS_TYPE_URL; return NS_OK; } + else if(!PL_strncasecmp(URL,"www.",4)) + { + *retType = HTTP_TYPE_URL; + return NS_OK; + } break; case 'u': case 'U': @@ -268,6 +332,31 @@ nsMimeURLUtils::URLType(const char *URL, PRInt32 *retType) return NS_OK; } +PRBool +IsThisAnAmbitiousLinkType(char *link, char *mailToTag, char **linkPrefix) +{ + if (!PL_strncasecmp(link, "www.", 4)) + { + *linkPrefix = PL_strdup("http://"); + return PR_TRUE; + } + else if (!PL_strncasecmp(link, "ftp.", 4)) + { + *linkPrefix = PL_strdup("ftp://"); + return PR_TRUE; + } + else if (mailToTag && *mailToTag) + { + if (!PL_strncasecmp(link, mailToTag, PL_strlen(mailToTag))) + { + *linkPrefix = PL_strdup("mailto:"); + return PR_TRUE; + } + } + + return PR_FALSE; +} + nsresult nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, char *output, int output_size, PRBool urls_only) @@ -282,6 +371,8 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, const char *cite_open2, *cite_close2; const char* color = NULL; + char *mailToTag = NULL; + if (urls_only) { cite_open1 = cite_close1 = ""; @@ -382,6 +473,7 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, } } + mailToTag = FindAmbitiousMailToTag(input); /* Normal lines are scanned for buried references to URL's Unfortunately, it may screw up once in a while (nobody's perfect) */ @@ -393,8 +485,17 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, this lets us match inside "---HTTP://XXX" but not inside of things like "NotHTTP://xxx" */ - int type = 0; - URLType(cp, &type); + int type = 0; + PRBool ambitiousHit; + + ambitiousHit = PR_FALSE; + if (mailToTag) + AmbitiousURLType(cp, &type, mailToTag); + if (!type) + URLType(cp, &type); + else + ambitiousHit = PR_TRUE; + if(!IS_SPACE(*cp) && (cp == input || (!IS_ALPHA(cp[-1]) && !IS_DIGIT(cp[-1]))) && (type) != 0) @@ -410,7 +511,6 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, *cp2 == ']' || *cp2 == '}' ) break; - } /* Check for certain punctuation characters on the end, and strip @@ -419,7 +519,7 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, (cp2[-1] == '.' || cp2[-1] == ',' || cp2[-1] == '!' || cp2[-1] == ';' || cp2[-1] == '-' || cp2[-1] == '?' || cp2[-1] == '#')) - cp2--; + cp2--; col += (cp2 - cp); @@ -433,9 +533,21 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, * 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)) + PRBool invalidHit = PR_FALSE; + + if ( (cp2 > cp && cp2[-1] == ':') || + !PL_strncmp(cp, "internal-", 9) ) + invalidHit = PR_TRUE; + + if (!invalidHit) + { + if ((ambitiousHit) && ((cp2-cp) < PL_strlen(mailToTag))) + invalidHit = PR_TRUE; + if ( (!ambitiousHit) && (cp2-cp < 7) ) + invalidHit = PR_TRUE; + } + + if (invalidHit) { nsCRT::memcpy(output_ptr, cp, cp2-cp); output_ptr += (cp2-cp); @@ -443,22 +555,36 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, } else { - char *quoted_url; - PRInt32 size_left = output_size - (output_ptr-output); + char *quoted_url; + PRBool rawLink = PR_FALSE; + PRInt32 size_left = output_size - (output_ptr-output); + char *linkPrefix = NULL; if(cp2-cp > size_left) return NS_ERROR_OUT_OF_MEMORY; nsCRT::memcpy(output_ptr, cp, cp2-cp); output_ptr[cp2-cp] = 0; + + rawLink = IsThisAnAmbitiousLinkType(output_ptr, mailToTag, &linkPrefix); 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); + + if (rawLink) + PR_snprintf(output_ptr, size_left, + "%s", + linkPrefix, + quoted_url, + quoted_url); + else + PR_snprintf(output_ptr, size_left, + "%s", + quoted_url, + quoted_url); + output_ptr += PL_strlen(output_ptr); PR_Free(quoted_url); + PR_FREEIF(linkPrefix); output_ptr += PL_strlen(output_ptr); } @@ -491,6 +617,9 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, *output_ptr++ = *cp; col++; } + + PR_FREEIF(mailToTag); + mailToTag = FindAmbitiousMailToTag(cp); } } @@ -509,6 +638,7 @@ nsMimeURLUtils::ScanForURLs(const char *input, int32 input_size, output_ptr += PL_strlen (cite_close1); } + PR_FREEIF(mailToTag); return NS_OK; }