summaryrefslogtreecommitdiffstats
path: root/libkdepim/linklocator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkdepim/linklocator.cpp')
-rw-r--r--libkdepim/linklocator.cpp466
1 files changed, 0 insertions, 466 deletions
diff --git a/libkdepim/linklocator.cpp b/libkdepim/linklocator.cpp
deleted file mode 100644
index 399c5d3b3..000000000
--- a/libkdepim/linklocator.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-/**
- * linklocator.cpp
- *
- * Copyright (c) 2002 Dave Corrie <kde@davecorrie.com>
- *
- * This file is part of KMail.
- *
- * KMail is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "linklocator.h"
-#include "pimemoticons.h"
-#include <kglobal.h>
-#include <kstandarddirs.h>
-#include <kstaticdeleter.h>
-#include <kmdcodec.h>
-#include <kdebug.h>
-
-#include <tqstylesheet.h>
-#include <tqfile.h>
-#include <tqregexp.h>
-
-#include <limits.h>
-
-TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonNameMap = 0;
-TQMap<TQString, TQString> *LinkLocator::s_smileyEmoticonHTMLCache = 0;
-
-static KStaticDeleter< TQMap<TQString, TQString> > smileyMapDeleter;
-static KStaticDeleter< TQMap<TQString, TQString> > smileyCacheDeleter;
-
-LinkLocator::LinkLocator(const TQString& text, int pos)
- : mText(text), mPos(pos), mMaxUrlLen(4096), mMaxAddressLen(255)
-{
- // If you change either of the above values for maxUrlLen or
- // maxAddressLen, then please also update the documentation for
- // setMaxUrlLen()/setMaxAddressLen() in the header file AND the
- // default values used for the maxUrlLen/maxAddressLen parameters
- // of convertToHtml().
-
- if ( !s_smileyEmoticonNameMap ) {
- smileyMapDeleter.setObject( s_smileyEmoticonNameMap,
- new TQMap<TQString, TQString>() );
- for ( int i = 0; i < EmotIcons::EnumSindex::COUNT; ++i ) {
- TQString imageName( EmotIcons::EnumSindex::enumToString[i] );
- imageName.truncate( imageName.length() - 2 ); //remove the _0 bit
- s_smileyEmoticonNameMap->insert( EmotIcons::smiley(i), imageName );
- }
- }
-
- if ( !s_smileyEmoticonHTMLCache )
- smileyCacheDeleter.setObject( s_smileyEmoticonHTMLCache,
- new TQMap<TQString, TQString>() );
-}
-
-void LinkLocator::setMaxUrlLen(int length)
-{
- mMaxUrlLen = length;
-}
-
-int LinkLocator::maxUrlLen() const
-{
- return mMaxUrlLen;
-}
-
-void LinkLocator::setMaxAddressLen(int length)
-{
- mMaxAddressLen = length;
-}
-
-int LinkLocator::maxAddressLen() const
-{
- return mMaxAddressLen;
-}
-
-TQString LinkLocator::getUrl()
-{
- TQString url;
- if(atUrl())
- {
- // handle cases like this: <link>http://foobar.org/</link>
- int start = mPos;
- while(mPos < (int)mText.length() && mText[mPos] > ' ' && mText[mPos] != '"' &&
- TQString("<>()[]").find(mText[mPos]) == -1)
- {
- ++mPos;
- }
- /* some URLs really end with: # / & - _ */
- const TQString allowedSpecialChars = TQString("#/&-_");
- while(mPos > start && mText[mPos-1].isPunct() &&
- allowedSpecialChars.find(mText[mPos-1]) == -1 )
- {
- --mPos;
- }
-
- url = mText.mid(start, mPos - start);
- if(isEmptyUrl(url) || mPos - start > maxUrlLen())
- {
- mPos = start;
- url = "";
- }
- else
- {
- --mPos;
- }
- }
- return url;
-}
-
-// keep this in sync with KMMainWin::slotUrlClicked()
-bool LinkLocator::atUrl() const
-{
- // the following characters are allowed in a dot-atom (RFC 2822):
- // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~
- const TQString allowedSpecialChars = TQString(".!#$%&'*+-/=?^_`{|}~");
-
- // the character directly before the URL must not be a letter, a number or
- // any other character allowed in a dot-atom (RFC 2822).
- if( ( mPos > 0 ) && ( mText[mPos-1].isLetterOrNumber() ||
- ( allowedSpecialChars.find( mText[mPos-1] ) != -1 ) ) )
- return false;
-
- TQChar ch = mText[mPos];
- return (ch=='h' && ( mText.mid(mPos, 7) == "http://" ||
- mText.mid(mPos, 8) == "https://") ) ||
- (ch=='v' && mText.mid(mPos, 6) == "vnc://") ||
- (ch=='f' && ( mText.mid(mPos, 7) == "fish://" ||
- mText.mid(mPos, 6) == "ftp://" ||
- mText.mid(mPos, 7) == "ftps://") ) ||
- (ch=='s' && ( mText.mid(mPos, 7) == "sftp://" ||
- mText.mid(mPos, 6) == "smb://") ) ||
- (ch=='m' && mText.mid(mPos, 7) == "mailto:") ||
- (ch=='w' && mText.mid(mPos, 4) == "www.") ||
- (ch=='f' && mText.mid(mPos, 4) == "ftp.") ||
- (ch=='n' && mText.mid(mPos, 5) == "news:");
- // note: no "file:" for security reasons
-}
-
-bool LinkLocator::isEmptyUrl(const TQString& url)
-{
- return url.isEmpty() ||
- url == "http://" ||
- url == "https://" ||
- url == "fish://" ||
- url == "ftp://" ||
- url == "ftps://" ||
- url == "sftp://" ||
- url == "smb://" ||
- url == "vnc://" ||
- url == "mailto" ||
- url == "www" ||
- url == "ftp" ||
- url == "news" ||
- url == "news://";
-}
-
-TQString LinkLocator::getEmailAddress()
-{
- TQString address;
-
- if ( mText[mPos] == '@' ) {
- // the following characters are allowed in a dot-atom (RFC 2822):
- // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~
- const TQString allowedSpecialChars = TQString(".!#$%&'*+-/=?^_`{|}~");
-
- // determine the local part of the email address
- int start = mPos - 1;
- while ( start >= 0 && mText[start].tqunicode() < 128 &&
- ( mText[start].isLetterOrNumber() ||
- mText[start] == '@' || // allow @ to find invalid email addresses
- allowedSpecialChars.find( mText[start] ) != -1 ) ) {
- if ( mText[start] == '@' )
- return TQString(); // local part contains '@' -> no email address
- --start;
- }
- ++start;
- // we assume that an email address starts with a letter or a digit
- while ( ( start < mPos ) && !mText[start].isLetterOrNumber() )
- ++start;
- if ( start == mPos )
- return TQString(); // local part is empty -> no email address
-
- // determine the domain part of the email address
- int dotPos = INT_MAX;
- int end = mPos + 1;
- while ( end < (int)mText.length() &&
- ( mText[end].isLetterOrNumber() ||
- mText[end] == '@' || // allow @ to find invalid email addresses
- mText[end] == '.' ||
- mText[end] == '-' ) ) {
- if ( mText[end] == '@' )
- return TQString(); // domain part contains '@' -> no email address
- if ( mText[end] == '.' )
- dotPos = TQMIN( dotPos, end ); // remember index of first dot in domain
- ++end;
- }
- // we assume that an email address ends with a letter or a digit
- while ( ( end > mPos ) && !mText[end - 1].isLetterOrNumber() )
- --end;
- if ( end == mPos )
- return TQString(); // domain part is empty -> no email address
- if ( dotPos >= end )
- return TQString(); // domain part doesn't contain a dot
-
- if ( end - start > maxAddressLen() )
- return TQString(); // too long -> most likely no email address
- address = mText.mid( start, end - start );
-
- mPos = end - 1;
- }
- return address;
-}
-
-TQString LinkLocator::convertToHtml(const TQString& plainText, int flags,
- int maxUrlLen, int maxAddressLen)
-{
- LinkLocator locator(plainText);
- locator.setMaxUrlLen(maxUrlLen);
- locator.setMaxAddressLen(maxAddressLen);
-
- TQString str;
- TQString result((TQChar*)0, (int)locator.mText.length() * 2);
- TQChar ch;
- int x;
- bool startOfLine = true;
- TQString emoticon;
-
- for (locator.mPos = 0, x = 0; locator.mPos < (int)locator.mText.length(); locator.mPos++, x++)
- {
- ch = locator.mText[locator.mPos];
- if ( flags & PreserveSpaces )
- {
- if (ch==' ')
- {
- if (startOfLine) {
- result += "&nbsp;";
- locator.mPos++, x++;
- startOfLine = false;
- }
- while (locator.mText[locator.mPos] == ' ')
- {
- result += " ";
- locator.mPos++, x++;
- if (locator.mText[locator.mPos] == ' ') {
- result += "&nbsp;";
- locator.mPos++, x++;
- }
- }
- locator.mPos--, x--;
- continue;
- }
- else if (ch=='\t')
- {
- do
- {
- result += "&nbsp;";
- x++;
- }
- while((x&7) != 0);
- x--;
- startOfLine = false;
- continue;
- }
- }
- if (ch=='\n')
- {
- result += "<br />";
- startOfLine = true;
- x = -1;
- continue;
- }
-
- startOfLine = false;
- if (ch=='&')
- result += "&amp;";
- else if (ch=='"')
- result += "&quot;";
- else if (ch=='<')
- result += "&lt;";
- else if (ch=='>')
- result += "&gt;";
- else
- {
- const int start = locator.mPos;
- if ( !(flags & IgnoreUrls) ) {
- str = locator.getUrl();
- if (!str.isEmpty())
- {
- TQString hyperlink;
- if(str.left(4) == "www.")
- hyperlink = "http://" + str;
- else if(str.left(4) == "ftp.")
- hyperlink = "ftp://" + str;
- else
- hyperlink = str;
-
- str = str.replace('&', "&amp;");
- result += "<a href=\"" + hyperlink + "\">" + str + "</a>";
- x += locator.mPos - start;
- continue;
- }
- str = locator.getEmailAddress();
- if(!str.isEmpty())
- {
- // len is the length of the local part
- int len = str.find('@');
- TQString localPart = str.left(len);
-
- // remove the local part from the result (as '&'s have been expanded to
- // &amp; we have to take care of the 4 additional characters per '&')
- result.truncate(result.length() - len - (localPart.contains('&')*4));
- x -= len;
-
- result += "<a href=\"mailto:" + str + "\">" + str + "</a>";
- x += str.length() - 1;
- continue;
- }
- }
- if ( flags & ReplaceSmileys ) {
- str = locator.getEmoticon();
- if ( ! str.isEmpty() ) {
- result += str;
- x += locator.mPos - start;
- continue;
- }
- }
- if ( flags & HighlightText ) {
- str = locator.highlightedText();
- if ( !str.isEmpty() ) {
- result += str;
- x += locator.mPos - start;
- continue;
- }
- }
- result += ch;
- }
- }
-
- return result;
-}
-
-TQString LinkLocator::pngToDataUrl( const TQString & iconPath )
-{
- if ( iconPath.isEmpty() )
- return TQString();
-
- TQFile pngFile( iconPath );
- if ( !pngFile.open( IO_ReadOnly | IO_Raw ) )
- return TQString();
-
- TQByteArray ba = pngFile.readAll();
- pngFile.close();
- return TQString::tqfromLatin1("data:image/png;base64,%1")
- .tqarg( KCodecs::base64Encode( ba ).data() );
-}
-
-
-TQString LinkLocator::getEmoticon()
-{
- // smileys have to be prepended by whitespace
- if ( ( mPos > 0 ) && !mText[mPos-1].isSpace() )
- return TQString();
-
- // since smileys start with ':', ';', '(' or '8' short circuit method
- const TQChar ch = mText[mPos];
- if ( ch !=':' && ch != ';' && ch != '(' && ch != '8' )
- return TQString();
-
- // find the end of the smiley (a smiley is at most 4 chars long and ends at
- // lineend or whitespace)
- const int MinSmileyLen = 2;
- const int MaxSmileyLen = 4;
- int smileyLen = 1;
- while ( ( smileyLen <= MaxSmileyLen ) &&
- ( mPos+smileyLen < (int)mText.length() ) &&
- !mText[mPos+smileyLen].isSpace() )
- smileyLen++;
- if ( smileyLen < MinSmileyLen || smileyLen > MaxSmileyLen )
- return TQString();
-
- const TQString smiley = mText.mid( mPos, smileyLen );
- if ( !s_smileyEmoticonNameMap->contains( smiley ) )
- return TQString(); // that's not a (known) smiley
-
- TQString htmlRep;
- if ( s_smileyEmoticonHTMLCache->contains( smiley ) ) {
- htmlRep = (*s_smileyEmoticonHTMLCache)[smiley];
- }
- else {
- const TQString imageName = (*s_smileyEmoticonNameMap)[smiley];
-
-#if KDE_IS_VERSION( 3, 3, 91 )
- const TQString iconPath = locate( "emoticons",
- EmotIcons::theme() +
- TQString::tqfromLatin1( "/" ) +
- imageName + TQString::tqfromLatin1(".png") );
-#else
- const TQString iconPath = locate( "data",
- TQString::tqfromLatin1( "kopete/pics/emoticons/" )+
- EmotIcons::theme() +
- TQString::tqfromLatin1( "/" ) +
- imageName + TQString::tqfromLatin1(".png") );
-#endif
-
- const TQString dataUrl = pngToDataUrl( iconPath );
- if ( dataUrl.isEmpty() ) {
- htmlRep = TQString();
- }
- else {
- // create an image tag (the text in attribute alt is used
- // for copy & paste) representing the smiley
- htmlRep = TQString("<img class=\"pimsmileyimg\" src=\"%1\" "
- "alt=\"%2\" title=\"%3\" width=\"16\" height=\"16\"/>")
- .tqarg( dataUrl,
- TQStyleSheet::escape( smiley ),
- TQStyleSheet::escape( smiley ) );
- }
- s_smileyEmoticonHTMLCache->insert( smiley, htmlRep );
- }
-
- if ( !htmlRep.isEmpty() )
- mPos += smileyLen - 1;
-
- return htmlRep;
-}
-
-TQString LinkLocator::highlightedText()
-{
- // formating symbols must be prepended with a whitespace
- if ( ( mPos > 0 ) && !mText[mPos-1].isSpace() )
- return TQString();
-
- const TQChar ch = mText[mPos];
- if ( ch != '/' && ch != '*' && ch != '_' )
- return TQString();
-
- TQRegExp re = TQRegExp( TQString("\\%1([0-9A-Za-z]+)\\%2").tqarg( ch ).tqarg( ch ) );
- if ( re.search( mText, mPos ) == mPos ) {
- uint length = re.matchedLength();
- // there must be a whitespace after the closing formating symbol
- if ( mPos + length < mText.length() && !mText[mPos + length].isSpace() )
- return TQString();
- mPos += length - 1;
- switch ( ch.latin1() ) {
- case '*':
- return "<b>" + re.cap( 1 ) + "</b>";
- case '_':
- return "<u>" + re.cap( 1 ) + "</u>";
- case '/':
- return "<i>" + re.cap( 1 ) + "</i>";
- }
- }
- return TQString();
-}
-