mimehdrline.cc
00001 /*************************************************************************** 00002 mimehdrline.cc - description 00003 ------------------- 00004 begin : Wed Oct 11 2000 00005 copyright : (C) 2000 by Sven Carstens 00006 email : s.carstens@gmx.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include <config.h> 00019 #include <iostream> 00020 #include <ctype.h> 00021 #include <stdlib.h> 00022 #include <stdio.h> 00023 00024 #include "mimehdrline.h" 00025 #include "rfcdecoder.h" 00026 00027 using namespace std; 00028 00029 const char *wdays[] = { 00030 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 00031 }; 00032 00033 const char *months[] = { 00034 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 00035 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 00036 }; 00037 00038 mimeHdrLine::mimeHdrLine (): 00039 mimeValue ((const char *) NULL), mimeLabel ((const char *) NULL) 00040 { 00041 } 00042 00043 mimeHdrLine::mimeHdrLine (const TQCString & aLabel, const TQCString & aValue): 00044 mimeValue (aValue), 00045 mimeLabel (aLabel) 00046 { 00047 } 00048 00049 mimeHdrLine::mimeHdrLine (mimeHdrLine * aHdrLine): 00050 mimeValue (aHdrLine->mimeValue), mimeLabel (aHdrLine->mimeLabel) 00051 { 00052 } 00053 00054 mimeHdrLine::~mimeHdrLine () 00055 { 00056 } 00057 00058 int 00059 mimeHdrLine::appendStr (const char *inCStr) 00060 { 00061 int retVal = 0; 00062 int skip; 00063 char *aCStr = (char *) inCStr; 00064 00065 if (aCStr) 00066 { 00067 skip = skipWS (aCStr); 00068 if (skip && !mimeLabel.isEmpty ()) 00069 { 00070 if (skip > 0) 00071 { 00072 mimeValue += TQCString (aCStr, skip + 1); 00073 aCStr += skip; 00074 retVal += skip; 00075 skip = parseFullLine (aCStr); 00076 mimeValue += TQCString (aCStr, skip + 1); 00077 retVal += skip; 00078 aCStr += skip; 00079 } 00080 } 00081 else 00082 { 00083 if (mimeLabel.isEmpty ()) 00084 return setStr (aCStr); 00085 } 00086 } 00087 return retVal; 00088 } 00089 00093 int 00094 mimeHdrLine::setStr (const char *inCStr) 00095 { 00096 int retVal = 0; 00097 char *aCStr = (char *) inCStr; 00098 // char *begin = aCStr; 00099 mimeLabel = TQCString ((const char *) NULL); 00100 mimeValue = TQCString ((const char *) NULL); 00101 00102 if (aCStr) 00103 { 00104 // can't have spaces on normal lines 00105 if (!skipWS (aCStr)) 00106 { 00107 int label = 0, advance; 00108 while ((advance = parseWord (&aCStr[label]))) 00109 { 00110 label += advance; 00111 } 00112 if (label && aCStr[label - 1] != ':') 00113 retVal = 0; 00114 else 00115 { 00116 mimeLabel = TQCString (aCStr, label); //length including zero 00117 retVal += label; 00118 aCStr += label; 00119 } 00120 } 00121 if (retVal) 00122 { 00123 int skip; 00124 skip = skipWS (aCStr); 00125 if (skip < 0) 00126 skip *= -1; 00127 aCStr += skip; 00128 retVal += skip; 00129 skip = parseFullLine (aCStr); 00130 mimeValue = TQCString (aCStr, skip + 1); 00131 retVal += skip; 00132 aCStr += skip; 00133 } 00134 else 00135 { 00136 //Skip malformed line 00137 while (*aCStr && *aCStr != '\r' && *aCStr != '\n') 00138 { 00139 retVal--; 00140 aCStr++; 00141 } 00142 if (*aCStr == '\r') 00143 { 00144 retVal--; 00145 aCStr++; 00146 } 00147 if (*aCStr == '\n') 00148 { 00149 retVal--; 00150 aCStr++; 00151 } 00152 } 00153 } 00154 else 00155 { 00156 //debug 00157 } 00158 return retVal; 00159 } 00160 00162 int 00163 mimeHdrLine::parseWord (const char *inCStr) 00164 { 00165 int retVal = 0; 00166 char *aCStr = (char *) inCStr; 00167 00168 if (aCStr && *aCStr) 00169 { 00170 if (*aCStr == '"') 00171 return mimeHdrLine::parseQuoted ('"', '"', aCStr); 00172 else 00173 return mimeHdrLine::parseHalfWord (aCStr); 00174 } 00175 else 00176 { 00177 //debug(); 00178 } 00179 return retVal; 00180 } 00181 00183 int 00184 mimeHdrLine::parseQuoted (char startQuote, char endQuote, const char *inCStr) 00185 { 00186 char *aCStr = (char *) inCStr; 00187 int retVal = 0; 00188 00189 if (aCStr && *aCStr) 00190 { 00191 if (*aCStr == startQuote) 00192 { 00193 aCStr++; 00194 retVal++; 00195 } 00196 else 00197 return 0; 00198 while (*aCStr && *aCStr != endQuote) 00199 { 00200 //skip over backticks 00201 if (*aCStr == '\\') 00202 { 00203 aCStr++; 00204 retVal++; 00205 } 00206 //eat this 00207 aCStr++; 00208 retVal++; 00209 } 00210 if (*aCStr == endQuote) 00211 { 00212 aCStr++; 00213 retVal++; 00214 } 00215 } 00216 else 00217 { 00218 //debug(); 00219 } 00220 return retVal; 00221 } 00222 00224 int 00225 mimeHdrLine::parseAlphaNum (const char *inCStr) 00226 { 00227 int retVal = 0; 00228 char *aCStr = (char *) inCStr; 00229 00230 if (aCStr) 00231 { 00232 while (*aCStr && isalnum (*aCStr)) 00233 { 00234 //skip over backticks 00235 if (*aCStr == '\\') 00236 { 00237 aCStr++; 00238 retVal++; 00239 } 00240 //eat this 00241 aCStr++; 00242 retVal++; 00243 } 00244 } 00245 else 00246 { 00247 //debug(); 00248 } 00249 return retVal; 00250 } 00251 00252 int 00253 mimeHdrLine::parseHalfWord (const char *inCStr) 00254 { 00255 int retVal = 0; 00256 char *aCStr = (char *) inCStr; 00257 00258 if (aCStr && *aCStr) 00259 { 00260 if (isalnum (*aCStr)) 00261 return mimeHdrLine::parseAlphaNum (aCStr); 00262 //skip over backticks 00263 if (*aCStr == '\\') 00264 { 00265 aCStr++; 00266 retVal++; 00267 } 00268 else if (!isspace (*aCStr)) 00269 { 00270 //eat this 00271 aCStr++; 00272 retVal++; 00273 } 00274 } 00275 else 00276 { 00277 //debug(); 00278 } 00279 return retVal; 00280 } 00281 00283 int 00284 mimeHdrLine::parseHalfLine (const char *inCStr) 00285 { 00286 int retVal = 0; 00287 char *aCStr = (char *) inCStr; 00288 00289 if (aCStr) 00290 { 00291 while (*aCStr && *aCStr != '\n') 00292 { 00293 //skip over backticks 00294 if (*aCStr == '\\') 00295 { 00296 aCStr++; 00297 retVal++; 00298 } 00299 //eat this 00300 aCStr++; 00301 retVal++; 00302 } 00303 if (*aCStr == '\n') 00304 { 00305 aCStr++; 00306 retVal++; 00307 } 00308 } 00309 else 00310 { 00311 //debug(); 00312 } 00313 return retVal; 00314 } 00315 00317 int 00318 mimeHdrLine::skipWS (const char *inCStr) 00319 { 00320 int retVal = 0; 00321 char *aCStr = (char *) inCStr; 00322 00323 if (aCStr && *aCStr) 00324 { 00325 while (*aCStr == ' ' || *aCStr == '\t') 00326 { 00327 aCStr++; 00328 retVal++; 00329 } 00330 //check out for continuation lines 00331 if (*aCStr == '\r') 00332 { 00333 aCStr++; 00334 retVal++; 00335 } 00336 if (*aCStr++ == '\n') 00337 if (*aCStr == '\t' || *aCStr == ' ') 00338 { 00339 int skip = mimeHdrLine::skipWS (aCStr); 00340 if (skip < 0) 00341 skip *= -1; 00342 retVal += 1 + skip; 00343 } 00344 else 00345 { 00346 retVal = -retVal - 1; 00347 } 00348 } 00349 else 00350 { 00351 //debug(); 00352 } 00353 return retVal; 00354 } 00355 00357 int 00358 mimeHdrLine::parseFullLine (const char *inCStr) 00359 { 00360 int retVal = 0; 00361 char *aCStr = (char *) inCStr; 00362 int skip; 00363 00364 if (aCStr) 00365 { 00366 //skip leading white space 00367 skip = skipWS (aCStr); 00368 if (skip > 0) 00369 { 00370 aCStr += skip; 00371 retVal += skip; 00372 } 00373 while (*aCStr) 00374 { 00375 int advance; 00376 00377 if ((advance = parseHalfLine (aCStr))) 00378 { 00379 retVal += advance; 00380 aCStr += advance; 00381 } 00382 else if ((advance = skipWS (aCStr))) 00383 { 00384 if (advance > 0) 00385 { 00386 retVal += advance; 00387 aCStr += advance; 00388 } 00389 else 00390 { 00391 retVal -= advance; 00392 break; 00393 } 00394 } 00395 else 00396 break; 00397 } 00398 } 00399 else 00400 { 00401 //debug(); 00402 } 00403 return retVal; 00404 } 00405 00407 int 00408 mimeHdrLine::parseSeparator (char separator, const char *inCStr) 00409 { 00410 char *aCStr = (char *) inCStr; 00411 int retVal = 0; 00412 int skip; 00413 00414 if (aCStr) 00415 { 00416 //skip leading white space 00417 skip = skipWS (aCStr); 00418 if (skip > 0) 00419 { 00420 aCStr += skip; 00421 retVal += skip; 00422 } 00423 while (*aCStr) 00424 { 00425 int advance; 00426 00427 if (*aCStr != separator) 00428 { 00429 if ((advance = mimeHdrLine::parseWord (aCStr))) 00430 { 00431 retVal += advance; 00432 aCStr += advance; 00433 } 00434 else if ((advance = mimeHdrLine::skipWS (aCStr))) 00435 { 00436 if (advance > 0) 00437 { 00438 retVal += advance; 00439 aCStr += advance; 00440 } 00441 else 00442 { 00443 retVal -= advance; 00444 break; 00445 } 00446 } 00447 else 00448 break; 00449 } 00450 else 00451 { 00452 //include separator in result 00453 retVal++; 00454 aCStr++; 00455 break; 00456 } 00457 } 00458 } 00459 else 00460 { 00461 //debug(); 00462 } 00463 return retVal; 00464 } 00465 00468 const TQCString& 00469 mimeHdrLine::getLabel () 00470 { 00471 return mimeLabel; 00472 } 00473 00475 const TQCString& 00476 mimeHdrLine::getValue () 00477 { 00478 return mimeValue; 00479 } 00480 00481 00482 // FIXME: very inefficient still 00483 TQCString 00484 mimeHdrLine::truncateLine(TQCString aLine, unsigned int truncate) 00485 { 00486 int cutHere; 00487 TQCString retVal; 00488 uint len = aLine.length(); 00489 00490 // see if we have a line of the form "key: value" (like "Subject: bla") 00491 // then we do not want to truncate between key and value 00492 int validStart = aLine.find(": "); 00493 if (validStart > -1) { 00494 validStart += 2; 00495 } 00496 while (len > truncate) { 00497 cutHere = aLine.findRev(' ', truncate); 00498 if (cutHere < 1 || cutHere < validStart) { 00499 cutHere = aLine.findRev('\t', truncate); 00500 if (cutHere < 1) { 00501 cutHere = aLine.find(' ', 1); 00502 if (cutHere < 1) { 00503 cutHere = aLine.find('\t', 1); 00504 if (cutHere < 1) { 00505 // simply truncate 00506 return aLine.left(truncate); 00507 } 00508 } 00509 } 00510 } 00511 00512 retVal += aLine.left(cutHere) + '\n'; 00513 int chop = len - cutHere; 00514 aLine = aLine.right(chop); 00515 len -= chop; 00516 } 00517 retVal += aLine; 00518 00519 return retVal; 00520 } 00521