libkdenetwork Library API Documentation

linklocator.cpp

00001 00023 #include "linklocator.h" 00024 00025 00026 LinkLocator::LinkLocator(const QString& text, int pos) 00027 : mText(text), mPos(pos), mMaxUrlLen(4096), mMaxAddressLen(255) 00028 { 00029 // If you change either of the above values for maxUrlLen or 00030 // maxAddressLen, then please also update the documentation for 00031 // setMaxUrlLen()/setMaxAddressLen() in the header file AND the 00032 // default values used for the maxUrlLen/maxAddressLen parameters 00033 // of convertToHtml(). 00034 } 00035 00036 void LinkLocator::setMaxUrlLen(int length) 00037 { 00038 mMaxUrlLen = length; 00039 } 00040 00041 int LinkLocator::maxUrlLen() const 00042 { 00043 return mMaxUrlLen; 00044 } 00045 00046 void LinkLocator::setMaxAddressLen(int length) 00047 { 00048 mMaxAddressLen = length; 00049 } 00050 00051 int LinkLocator::maxAddressLen() const 00052 { 00053 return mMaxAddressLen; 00054 } 00055 00056 QString LinkLocator::getUrl() 00057 { 00058 QString url; 00059 if(atUrl()) 00060 { 00061 // handle cases like this: <link>http://foobar.org/</link> 00062 int start = mPos; 00063 while(mPos < (int)mText.length() && mText[mPos] > ' ' && mText[mPos] != '"' && 00064 QString("<>()[]").find(mText[mPos]) == -1) 00065 { 00066 ++mPos; 00067 } 00068 /* some URLs really end with: # / & */ 00069 const QString allowedSpecialChars = QString("#/&"); 00070 while(mPos > start && mText[mPos-1].isPunct() && 00071 allowedSpecialChars.find(mText[mPos-1]) == -1 ) 00072 { 00073 --mPos; 00074 } 00075 00076 url = mText.mid(start, mPos - start); 00077 if(isEmptyUrl(url) || mPos - start > maxUrlLen()) 00078 { 00079 mPos = start; 00080 url = ""; 00081 } 00082 else 00083 { 00084 --mPos; 00085 } 00086 } 00087 return url; 00088 } 00089 00090 // keep this in sync with KMMainWin::slotUrlClicked() 00091 bool LinkLocator::atUrl() const 00092 { 00093 // the following characters are allowed in a dot-atom (RFC 2822): 00094 // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~ 00095 const QString allowedSpecialChars = QString(".!#$%&'*+-/=?^_`{|}~"); 00096 00097 // the character directly before the URL must not be a letter, a number or 00098 // any other character allowed in a dot-atom (RFC 2822). 00099 if( ( mPos > 0 ) && ( mText[mPos-1].isLetterOrNumber() || 00100 ( allowedSpecialChars.find( mText[mPos-1] ) != -1 ) ) ) 00101 return false; 00102 00103 QChar ch = mText[mPos]; 00104 return (ch=='h' && ( mText.mid(mPos, 7) == "http://" || 00105 mText.mid(mPos, 8) == "https://") ) || 00106 (ch=='v' && mText.mid(mPos, 6) == "vnc://") || 00107 (ch=='f' && ( mText.mid(mPos, 6) == "ftp://" || 00108 mText.mid(mPos, 7) == "ftps://") ) || 00109 (ch=='s' && ( mText.mid(mPos, 7) == "sftp://" || 00110 mText.mid(mPos, 6) == "smb://") ) || 00111 (ch=='m' && mText.mid(mPos, 7) == "mailto:") || 00112 (ch=='w' && mText.mid(mPos, 4) == "www.") || 00113 (ch=='f' && mText.mid(mPos, 4) == "ftp."); 00114 // note: no "file:" for security reasons 00115 } 00116 00117 bool LinkLocator::isEmptyUrl(const QString& url) 00118 { 00119 return url.isEmpty() || 00120 url == "http://" || 00121 url == "https://" || 00122 url == "ftp://" || 00123 url == "ftps://" || 00124 url == "sftp://" || 00125 url == "smb://" || 00126 url == "vnc://" || 00127 url == "mailto" || 00128 url == "www" || 00129 url == "ftp"; 00130 } 00131 00132 QString LinkLocator::getEmailAddress() 00133 { 00134 QString address; 00135 00136 if(mText[mPos] == '@') 00137 { 00138 // the following characters are allowed in a dot-atom (RFC 2822): 00139 // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~ 00140 const QString allowedSpecialChars = QString(".!#$%&'*+-/=?^_`{|}~"); 00141 00142 // determine the local part of the email address 00143 int start = mPos - 1; 00144 while (start >= 0 && mText[start].unicode() < 128 && 00145 (mText[start].isLetterOrNumber() || 00146 mText[start] == '@' || // allow @ to find invalid email addresses 00147 allowedSpecialChars.find(mText[start]) != -1)) 00148 { 00149 --start; 00150 } 00151 ++start; 00152 // we assume that an email address starts with a letter or a digit 00153 while (allowedSpecialChars.find(mText[start]) != -1) 00154 ++start; 00155 00156 // determine the domain part of the email address 00157 int end = mPos + 1; 00158 while (end < (int)mText.length() && 00159 (mText[end].isLetterOrNumber() || 00160 mText[end] == '@' || // allow @ to find invalid email addresses 00161 allowedSpecialChars.find(mText[end]) != -1)) 00162 { 00163 ++end; 00164 } 00165 // we assume that an email address ends with a letter or a digit 00166 while (allowedSpecialChars.find(mText[end - 1]) != -1) 00167 --end; 00168 00169 address = mText.mid(start, end - start); 00170 if(isEmptyAddress(address) || end - start > maxAddressLen() || address.contains('@') != 1) 00171 address = ""; 00172 00173 if(!address.isEmpty()) 00174 mPos = end - 1; 00175 } 00176 return address; 00177 } 00178 00179 bool LinkLocator::isEmptyAddress(const QString& address) 00180 { 00181 return address.isEmpty() || 00182 address[0] == '@' || 00183 address[address.length() - 1] == '@'; 00184 } 00185 00186 QString LinkLocator::convertToHtml(const QString& plainText, bool preserveBlanks, 00187 int maxUrlLen, int maxAddressLen) 00188 { 00189 LinkLocator locator(plainText); 00190 locator.setMaxUrlLen(maxUrlLen); 00191 locator.setMaxAddressLen(maxAddressLen); 00192 00193 QString str; 00194 QString result((QChar*)0, (int)locator.mText.length() * 2); 00195 QChar ch; 00196 int x; 00197 bool startOfLine = true; 00198 00199 for (locator.mPos = 0, x = 0; locator.mPos < (int)locator.mText.length(); locator.mPos++, x++) 00200 { 00201 ch = locator.mText[locator.mPos]; 00202 if (preserveBlanks) 00203 { 00204 if (ch==' ') 00205 { 00206 if (startOfLine) { 00207 result += "&nbsp;"; 00208 locator.mPos++, x++; 00209 startOfLine = false; 00210 } 00211 while (locator.mText[locator.mPos] == ' ') 00212 { 00213 result += " "; 00214 locator.mPos++, x++; 00215 if (locator.mText[locator.mPos] == ' ') { 00216 result += "&nbsp;"; 00217 locator.mPos++, x++; 00218 } 00219 } 00220 locator.mPos--, x--; 00221 continue; 00222 } 00223 else if (ch=='\t') 00224 { 00225 do 00226 { 00227 result += "&nbsp;"; 00228 x++; 00229 } 00230 while((x&7) != 0); 00231 x--; 00232 startOfLine = false; 00233 continue; 00234 } 00235 } 00236 if (ch=='\n') 00237 { 00238 result += "<br />"; 00239 startOfLine = true; 00240 x = -1; 00241 continue; 00242 } 00243 00244 startOfLine = false; 00245 if (ch=='&') 00246 result += "&amp;"; 00247 else if (ch=='"') 00248 result += "&quot;"; 00249 else if (ch=='<') 00250 result += "&lt;"; 00251 else if (ch=='>') 00252 result += "&gt;"; 00253 else 00254 { 00255 int start = locator.mPos; 00256 str = locator.getUrl(); 00257 if(!str.isEmpty()) 00258 { 00259 QString hyperlink; 00260 if(str.left(4) == "www.") 00261 hyperlink = "http://" + str; 00262 else if(str.left(4) == "ftp.") 00263 hyperlink = "ftp://" + str; 00264 else 00265 hyperlink = str; 00266 00267 str = str.replace('&', "&amp;"); 00268 result += "<a href=\"" + hyperlink + "\">" + str + "</a>"; 00269 x += locator.mPos - start; 00270 } 00271 else 00272 { 00273 str = locator.getEmailAddress(); 00274 if(!str.isEmpty()) 00275 { 00276 // len is the length of the local part 00277 int len = str.find('@'); 00278 QString localPart = str.left(len); 00279 00280 // remove the local part from the result (as '&'s have been expanded to 00281 // &amp; we have to take care of the 4 additional characters per '&') 00282 result.truncate(result.length() - len - (localPart.contains('&')*4)); 00283 x -= len; 00284 00285 result += "<a href=\"mailto:" + str + "\">" + str + "</a>"; 00286 x += str.length() - 1; 00287 } 00288 else 00289 { 00290 result += ch; 00291 } 00292 } 00293 } 00294 } 00295 00296 return result; 00297 } 00298 00299
KDE Logo
This file is part of the documentation for libkdenetwork Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 27 12:48:47 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003