Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

blueconvert.cpp

00001 /*! 00002 @class BlueConvert 00003 @brief Konvertiert 7bit GSM Zeichensaetze vom Telephon und zurueck. 00004 @author Thomas Gemperli, <bluephone@gemperli.net> 00005 @version 1.0 00006 @date 2004-08-03 00007 @par This program is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU General Public License. 00009 @file blueconvert.cpp 00010 */ 00011 00012 00013 #include "blueconvert.h" 00014 00015 00016 /** 00017 * BlueConvert Konstruktor 00018 * Erstellt ein BlueConvert Objekt. 00019 */ 00020 BlueConvert::BlueConvert() 00021 { 00022 } 00023 00024 00025 /** 00026 * BlueConvert Destruktor 00027 */ 00028 BlueConvert::~BlueConvert() 00029 { 00030 } 00031 00032 00033 /** 00034 * Diese Methode liefert den decodierten Sender einer SMS zurueck. 00035 * Rueckgabewert: QString m_sender 00036 */ 00037 QString BlueConvert::getSender() 00038 { 00039 return m_sender; 00040 } 00041 00042 00043 /** 00044 * Diese Methode liefert das decodierte Datum einer SMS zurueck. 00045 * Rueckgabewert: QString m_date 00046 */ 00047 QString BlueConvert::getDate() 00048 { 00049 return m_date; 00050 } 00051 00052 00053 /** 00054 * Diese Methode liefert die decodierte Nachricht einer SMS zurueck. 00055 * Rueckgabewert: QString m_message 00056 */ 00057 QString BlueConvert::getMessage() 00058 { 00059 return m_message; 00060 } 00061 00062 00063 /** 00064 * Diese Methode liefert die encodierte PDU zurueck. 00065 * Rueckgabewert: QString m_PDU 00066 */ 00067 QString BlueConvert::getPdu() 00068 { 00069 return m_PDU; 00070 } 00071 00072 00073 /** 00074 * Diese Methode extrahiert die einzelnen Daten aus dem PDU Format. 00075 * Ist v.a. String Akrobatik. Eine gute Erklaerung zum Thema befindet sich da: 00076 * http://www.nobbi.com/sms_pdu.htm 00077 * Parameter: QString input, int Length 00078 */ 00079 void BlueConvert::extractPduData(QString PDU) 00080 { 00081 m_posInPdu = 0; 00082 00083 m_PDU = PDU; 00084 00085 /* Extrahiere allgemeine Daten des PDU Blockes wie 00086 die Länge der SMSC-Adresse (Service Center und Typ dieser (National/International) */ 00087 m_smscLen = m_PDU.left(2).toInt(0, 16); 00088 m_smscType = m_PDU.mid((m_smscLen*2)+2,2).toInt(0,16); 00089 00090 /* Weiter im PDU Block */ 00091 m_posInPdu = (m_smscLen*2)+4; 00092 if (m_smscType&1) 00093 { 00094 m_posInPdu += 2; 00095 } 00096 00097 /* Extrahiere die Laenge der Sendernummer */ 00098 m_senderLength = (m_PDU.mid(m_posInPdu,2)).toInt(0,16); 00099 00100 /* Extrahiere den Typ der Telephonnummer (National/International) */ 00101 m_senderType = (m_PDU.mid(m_posInPdu+2,2)); 00102 if (m_senderLength % 2) 00103 { 00104 m_senderLength++; 00105 } 00106 00107 /* Extrahiere die Nummer des Senders. Die erste wirklich interessante Information */ 00108 m_sender = m_PDU.mid(m_posInPdu+4, m_senderLength); 00109 m_sender = decodeBCD(m_sender); 00110 if (m_sender.contains("F")) 00111 { 00112 m_sender.truncate(m_sender.length()-1); 00113 } 00114 00115 if (m_senderType=="91") 00116 { 00117 m_sender.prepend("+"); 00118 } 00119 00120 m_posInPdu +=4+m_senderLength; 00121 00122 00123 /* Die naechsten 4 Bits interssieren uns nicht. (Protocol Identifier & Data Coding Scheme) */ 00124 m_posInPdu +=4; 00125 00126 /* Extrahiere das Sendedatum des SMS */ 00127 if (!(m_smscType&1)) 00128 { 00129 m_date = m_PDU.mid(m_posInPdu, 14); 00130 m_date = decodeBCD(m_date); 00131 00132 m_posInPdu +=14; 00133 } 00134 else if (!(m_smscType&64)) 00135 { 00136 m_posInPdu += 2; 00137 } 00138 00139 /* Stelle fest, ob es sich um eine ueberlange SMS handelt (mehr als 160 Zeichen) 00140 Und setze m_posInPdu entsprechend */ 00141 m_messageLength = (m_PDU.mid(m_posInPdu, 2)).toInt(0,16); 00142 m_posInPdu +=2; 00143 00144 if (m_smscType&64) 00145 { 00146 m_udhLength=m_PDU.mid(m_posInPdu, 2).toInt(0,16); 00147 m_posInPdu +=2; 00148 m_rp=m_PDU.mid(m_posInPdu, 2).toInt(0,16); 00149 m_posInPdu +=2; 00150 m_rplength=m_PDU.mid(m_posInPdu, 2).toInt(0,16); 00151 m_posInPdu +=2; 00152 00153 for (int i=0;i<m_rplength;i++) 00154 { 00155 m_ie[i]=m_PDU.mid(m_posInPdu, 2).toInt(0,16); 00156 m_posInPdu +=2; 00157 } 00158 m_posInPdu-=2*(m_udhLength+1); 00159 } 00160 00161 /* Extrahiere die eigentliche Nachricht des SMS */ 00162 m_message = m_PDU.mid(m_posInPdu); 00163 m_message = decodeMessage(m_message); 00164 if (m_smscType&64) 00165 { 00166 int toskip=(m_udhLength+1)*8/7; 00167 00168 if ((m_udhLength+1)*8%7) 00169 { 00170 toskip++; 00171 } 00172 00173 m_message=m_message.mid(toskip); 00174 } 00175 } 00176 00177 00178 /** 00179 * Diese Methode swappt Bits. 00180 * Einige Daten (z.B. smsc Nummer) in einer PDU sind BCD codiert. 00181 * Parameter: QString toSwap 00182 * Rueckgabewert: QString swapped 00183 */ 00184 QString BlueConvert::decodeBCD(QString toSwap) 00185 { 00186 m_swapped = ""; 00187 00188 for (unsigned int i=0; i<=toSwap.length(); i+=2) 00189 { 00190 m_swapped.append(toSwap.mid(i+1,1)); 00191 m_swapped.append(toSwap.mid(i,1)); 00192 } 00193 00194 return m_swapped; 00195 } 00196 00197 00198 /** 00199 * Diese Methode erstellt einen PDU Datenblock. 00200 * Ist v.a. String Akrobatik. Eine gute Erklaerung zum Thema befindet sich da: 00201 * http://www.nobbi.com/sms_pdu.htm 00202 * Parameter: QString recipient, QString message, int index, int id 00203 */ 00204 void BlueConvert::createPduData(QString recipient, QString message, int index, int id) 00205 { 00206 m_recipient = recipient; 00207 m_message = message; 00208 m_index = index; 00209 m_id = id; 00210 00211 /* Haben wir eine ueberlange Message? 00212 Wenn ja, wird die Groesse dieser Ueberlaenge spaeter gebraucht */ 00213 m_longMessage=m_message.length()>160; 00214 00215 /* Eine ueberlange Message hat einen anderen Header als eine "nornale" */ 00216 m_PDU = m_longMessage?"004100":"000100"; 00217 00218 /* Setze den Typ der Empfaengernummer. (National) */ 00219 m_recipientType = "85"; 00220 00221 /* Ermittle den Typ der Empfaengernummer. Falls International, setze dies (91). */ 00222 if (m_recipient.left(1)=="+") 00223 { 00224 m_recipient=m_recipient.mid(1); 00225 m_recipientType = "91"; 00226 } 00227 00228 /* Ermittle die Laenge der Empfaengernummer. */ 00229 m_recipientLength = m_recipient.length(); 00230 m_recipientLengthHex.setNum(m_recipientLength,16); 00231 if (m_recipientLength < 16) 00232 { 00233 m_PDU.append("0"); 00234 } 00235 m_PDU.append(m_recipientLengthHex); 00236 00237 /* Setze den Typ der Empfaengernummer. (National/International) */ 00238 m_PDU.append(m_recipientType); 00239 00240 /* Fuege die BCD encodierte Empfaengernummer der PDU hinzu */ 00241 if ((m_recipientLength%2) != 0) 00242 { 00243 m_recipient.append("F"); 00244 } 00245 m_PDU.append(decodeBCD(m_recipient)); 00246 00247 /* Fuege Protokoll Id and Data Coding Scheme der PDU hinzu. Die sind immer gleich (beide 00). */ 00248 m_PDU.append("0000"); 00249 00250 /* Konvertiere die Nachricht in das PDU Format. */ 00251 if (m_longMessage) 00252 { 00253 m_encodedMessage = encodeMessage(m_message.mid(153*(m_index-1),153*m_index),m_longMessage); 00254 } 00255 else 00256 { 00257 m_encodedMessage = encodeMessage(m_message,m_longMessage); 00258 } 00259 00260 /* Falls es sich um eine ueberlange Nachricht handelt, ermittle die Ueberlaenge 00261 und setze die Gesamtlaenge entsprechend. */ 00262 if (m_longMessage) 00263 { 00264 m_carryoverLength.setNum(m_messageLength+7, 16); 00265 00266 if (m_messageLength < 16) 00267 { 00268 m_carryoverLength.prepend("0"); 00269 } 00270 00271 m_PDU.append(m_carryoverLength); 00272 m_PDU.append("050003"); 00273 00274 int chars=m_message.length(); 00275 int numSMS=chars/153; 00276 00277 if (chars%153) 00278 { 00279 numSMS++; 00280 } 00281 00282 m_carryoverLength.setNum(m_id, 16); 00283 00284 if (m_id<16) 00285 { 00286 m_carryoverLength.prepend("0"); 00287 } 00288 m_PDU.append(m_carryoverLength); 00289 00290 m_carryoverLength.setNum(numSMS, 16); 00291 00292 if (numSMS<16) 00293 { 00294 m_carryoverLength.prepend("0"); 00295 } 00296 00297 m_PDU.append(m_carryoverLength); 00298 00299 m_carryoverLength.setNum(m_index, 16); 00300 00301 if (m_index<16) 00302 { 00303 m_carryoverLength.prepend("0"); 00304 } 00305 00306 m_PDU.append(m_carryoverLength); 00307 } 00308 else 00309 { 00310 m_carryoverLength.setNum(m_messageLength, 16); 00311 00312 if (m_messageLength < 16) 00313 { 00314 m_carryoverLength.prepend("0"); 00315 } 00316 00317 m_PDU.append(m_carryoverLength); 00318 } 00319 00320 /* Fuege die Nachricht der PDU hinzu. Fertig ist das SMS (in m_PDU). */ 00321 m_PDU.append(m_encodedMessage); 00322 00323 } 00324 00325 00326 /** 00327 * convert_from_gsm 00328 * Diese Methode konvertiert den GSM Zeichensatz in Unicode. 00329 * Parameter: QString input 00330 * Rueckgabewert: QString UnicodeString 00331 */ 00332 QString BlueConvert::convert_from_gsm (const QString& input) 00333 { 00334 QString retval; 00335 for (uint i = 0;i < input.length(); i++) { 00336 const ushort& a = input[i].unicode(); 00337 switch (a) { 00338 default: 00339 retval += a; 00340 break; 00341 case 0x80: // commercial at 00342 /* 00343 * we expect this as 0x80 instead of 0x00 00344 * to avoid problem with C's char* 00345 */ 00346 retval += 0x0040; 00347 break; 00348 case 0x01: // pound sign 00349 retval += 0x00a3; 00350 break; 00351 case 0x02: // dollar sign 00352 retval += 0x0024; 00353 break; 00354 case 0x03: // yen sign 00355 retval += 0x00a5; 00356 break; 00357 case 0x04: // small 'e' with grave 00358 retval += 0x00e8; 00359 break; 00360 case 0x05: // small 'e' with acute 00361 retval += 0x00e9; 00362 break; 00363 case 0x06: // small 'u' with grave 00364 retval += 0x00f9; 00365 break; 00366 case 0x07: // small 'i' with grave 00367 retval += 0x00ec; 00368 break; 00369 case 0x08: // small 'o' with grave 00370 retval += 0x00f2; 00371 break; 00372 case 0x09: // small/capital 'c' with cedilla (we map to small) 00373 retval += 0x00e7; // or 0x00c7 ? 00374 break; 00375 case 0x0b: // capital 'O' with stroke 00376 retval += 0x00d8; 00377 break; 00378 case 0x0c: // small 'o' with stroke 00379 retval += 0x00f8; 00380 break; 00381 case 0x0e: // capital 'A' with ring above 00382 retval += 0x00c5; 00383 break; 00384 case 0x0f: // small 'a' with ring above 00385 retval += 0x00e5; 00386 break; 00387 case 0x10: // capital delta 00388 retval += 0x0394; 00389 break; 00390 case 0x11: // underscore / low line 00391 retval += 0x005f; 00392 break; 00393 case 0x12: // capital phi 00394 retval += 0x03a6; 00395 break; 00396 case 0x13: // capital gamma 00397 retval += 0x0393; 00398 break; 00399 case 0x14: // capital lambda 00400 retval += 0x039b; 00401 break; 00402 case 0x15: // capital omega 00403 retval += 0x03a9; 00404 break; 00405 case 0x16: // capital pi 00406 retval += 0x03a0; 00407 break; 00408 case 0x17: // capital psi 00409 retval += 0x03a8; 00410 break; 00411 case 0x18: // capital sigma 00412 retval += 0x03a3; 00413 break; 00414 case 0x19: // capital theta 00415 retval += 0x0398; 00416 break; 00417 case 0x1a: // capital xi 00418 retval += 0x039e; 00419 break; 00420 case 0x1b: 00421 ++i; 00422 switch (a) { 00423 default: // non-breaking space 00424 --i; 00425 retval += 0x00a0; 00426 break; 00427 case 0x1a: // form feed 00428 retval += 0x000c; 00429 break; 00430 case 0x14: // circumflex accent 00431 retval += 0x005e; 00432 break; 00433 case 0x28: // left curly bracket 00434 retval += 0x007b; 00435 break; 00436 case 0x29: // right curly bracket 00437 retval += 0x007d; 00438 break; 00439 case 0x2f: // reverse solidus 00440 retval += 0x005c; 00441 break; 00442 case 0x3c: // left square bracket 00443 retval += 0x005b; 00444 break; 00445 case 0x3d: // tilde 00446 retval += 0x007e; 00447 break; 00448 case 0x3e: // right square bracket 00449 retval += 0x005d; 00450 break; 00451 case 0x40: // vertical line 00452 retval += 0x007c; 00453 break; 00454 case 0x65: // Euro sign 00455 retval += 0x20ac; 00456 break; 00457 } 00458 break; 00459 case 0x1c: // capital 'AE' 00460 retval += 0x00c6; 00461 break; 00462 case 0x1d: // small 'ae' 00463 retval += 0x00e6; 00464 break; 00465 case 0x1e: // small sharp s (german) 00466 retval += 0x00df; 00467 break; 00468 case 0x1f: // capital 'E' with acute 00469 retval += 0x00c9; 00470 break; 00471 case 0x24: // currency sign 00472 //retval += 0x20ac; 00473 retval += 0x00a4; 00474 break; 00475 case 0x40: // inverted exclamation mark 00476 retval += 0x00a1; 00477 break; 00478 case 0x5b: // capital 'A' with diaeresis 00479 retval += 0x00c4; 00480 break; 00481 case 0x5c: // capital 'O' with diaeresis 00482 retval += 0x00d6; 00483 break; 00484 case 0x5d: // capital 'N' with tilde 00485 retval += 0x00d1; 00486 break; 00487 case 0x5e: // capital 'U' with diaeresis 00488 retval += 0x00dc; 00489 break; 00490 case 0x5f: // section sign 00491 retval += 0x00a7; 00492 break; 00493 case 0x60: // inverted question mark 00494 retval += 0x00bf; 00495 break; 00496 case 0x7b: // small 'a' with diaeresis 00497 retval += 0x00e4; 00498 break; 00499 case 0x7c: // small 'o' with diaeresis 00500 retval += 0x00f6; 00501 break; 00502 case 0x7d: // small 'n' with tilde 00503 retval += 0x00f1; 00504 break; 00505 case 0x7e: // small 'u' with diaeresis 00506 retval += 0x00fc; 00507 break; 00508 case 0x7f: // small 'a' with grave 00509 retval += 0x00e0; 00510 break; 00511 } 00512 } 00513 return retval; 00514 } 00515 00516 00517 00518 /** 00519 * convert_to_gsm 00520 * Diese Methode konvertiert Unicode in den GSM Zeichensatz. 00521 * Parameter: QString input 00522 * Rueckgabewert: QString GSMString 00523 */ 00524 QString BlueConvert::convert_to_gsm (const QString& input) 00525 { 00526 QString retval; 00527 00528 for (uint i = 0; i < input.length(); i++) { 00529 const ushort& a = input[i].unicode(); 00530 switch (a) { 00531 default: 00532 if (a < 0x0080 && ( 00533 /* 00534 * see Unicode table for descriptions 00535 */ 00536 a == 0x000A || 00537 a == 0x000D || 00538 (a >= 0x0020 && a <= 0x0023) || 00539 (a >= 0x0025 && a <= 0x003f) || 00540 (a >= 0x0041 && a <= 0x005a) || 00541 (a >= 0x0061 && a <= 0x007a))) { 00542 retval += a; 00543 } 00544 break; 00545 case 0x0040: // commercial at 00546 /* 00547 * we map this to 0x80 instead of 0x00 to avoid problem with C's char* 00548 * just make sure you only use the last 7 bits of these values, 00549 * you must do that anyway 00550 */ 00551 retval += 0x80; 00552 break; 00553 case 0x00a3: // pound sign 00554 retval += 0x01; 00555 break; 00556 case 0x0024: // dollar sign 00557 retval += 0x02; 00558 break; 00559 case 0x00a5: // yen sign 00560 retval += 0x03; 00561 break; 00562 case 0x00e8: // small 'e' with grave 00563 retval += 0x04; 00564 break; 00565 case 0x00e9: // small 'e' with acute 00566 retval += 0x05; 00567 break; 00568 case 0x00f9: // small 'u' with grave 00569 retval += 0x06; 00570 break; 00571 case 0x00ec: // small 'i' with grave 00572 retval += 0x07; 00573 break; 00574 case 0x00f2: // small 'o' with grave 00575 retval += 0x08; 00576 break; 00577 case 0x00c7: // capital 'C' with cedilla 00578 case 0x00e7: // small 'c' with cedilla 00579 retval += 0x09; 00580 break; 00581 case 0x00d8: // capital 'O' with stroke 00582 retval += 0x0b; 00583 break; 00584 case 0x00f8: // small 'o' with stroke 00585 retval += 0x0c; 00586 break; 00587 case 0x00c5: // capital 'A' with ring above 00588 retval += 0x0e; 00589 break; 00590 case 0x00e5: // small 'a' with ring above 00591 retval += 0x0f; 00592 break; 00593 case 0x0394: // capital delta 00594 retval += 0x10; 00595 break; 00596 case 0x005f: // underscore / low line 00597 retval += 0x11; 00598 break; 00599 case 0x03a6: // capital phi 00600 retval += 0x12; 00601 break; 00602 case 0x0393: // capital gamma 00603 retval += 0x13; 00604 break; 00605 case 0x039b: // capital lambda 00606 retval += 0x14; 00607 break; 00608 case 0x03a9: // capital omega 00609 retval += 0x15; 00610 break; 00611 case 0x03a0: // capital pi 00612 retval += 0x16; 00613 break; 00614 case 0x03a8: // capital psi 00615 retval += 0x17; 00616 break; 00617 case 0x03a3: // capital sigma 00618 retval += 0x18; 00619 break; 00620 case 0x0398: // capital theta 00621 retval += 0x19; 00622 break; 00623 case 0x039e: // capital xi 00624 retval += 0x1a; 00625 break; 00626 case 0x000c: // form feed 00627 retval += 0x1b; 00628 retval += 0x0a; 00629 break; 00630 case 0x005e: // circumflex accent 00631 retval += 0x1b; 00632 retval += 0x14; 00633 break; 00634 case 0x007b: // left curly bracket 00635 retval += 0x1b; 00636 retval += 0x28; 00637 break; 00638 case 0x007d: // right curly bracket 00639 retval += 0x1b; 00640 retval += 0x29; 00641 break; 00642 case 0x005c: // reverse solidus (back slash) 00643 retval += 0x1b; 00644 retval += 0x2f; 00645 break; 00646 case 0x005b: // left square bracket 00647 retval += 0x1b; 00648 retval += 0x3c; 00649 break; 00650 case 0x007e: // tilde 00651 retval += 0x1b; 00652 retval += 0x3d; 00653 break; 00654 case 0x005d: // right square bracket 00655 retval += 0x1b; 00656 retval += 0x3e; 00657 break; 00658 case 0x007c: // vertical line 00659 retval += 0x1b; 00660 retval += 0x40; 00661 break; 00662 case 0x20ac: // Euro sign 00663 retval += 0x1b; 00664 retval += 0x65; 00665 break; 00666 case 0x00c6: // capital 'AE' 00667 retval += 0x1c; 00668 break; 00669 case 0x00e6: // small 'ae' 00670 retval += 0x1d; 00671 break; 00672 case 0x00df: // small sharp s (german) 00673 retval += 0x1e; 00674 break; 00675 case 0x00c9: // capital 'E' with acute 00676 retval += 0x1f; 00677 break; 00678 case 0x00a4: // currency sign 00679 case 0x00b0: // degree sign (not offical, preference of author) 00680 retval += 0x24; 00681 break; 00682 case 0x00a1: // inverted exclamation mark 00683 retval += 0x40; 00684 break; 00685 case 0x0391: // capital alpha 00686 retval += 0x41; 00687 break; 00688 case 0x0392: // capital beta 00689 retval += 0x42; 00690 break; 00691 case 0x0395: // capital epsilon 00692 retval += 0x45; 00693 break; 00694 case 0x0397: // capital eta 00695 retval += 0x48; 00696 break; 00697 case 0x0399: // capital iota 00698 retval += 0x49; 00699 break; 00700 case 0x039a: // capital kappa 00701 retval += 0x4b; 00702 break; 00703 case 0x039c: // capital mu 00704 retval += 0x4d; 00705 break; 00706 case 0x039d: // capital nu 00707 retval += 0x4e; 00708 break; 00709 case 0x039f: // capital omicron 00710 retval += 0x4f; 00711 break; 00712 case 0x03a1: // capital rho 00713 retval += 0x50; 00714 break; 00715 case 0x03a4: // capital tau 00716 retval += 0x54; 00717 break; 00718 case 0x03a5: // capital upsilon 00719 retval += 0x55; 00720 break; 00721 case 0x03a7: // capital chi 00722 retval += 0x58; 00723 break; 00724 case 0x0396: // capital zeta 00725 retval += 0x5a; 00726 break; 00727 case 0x00c4: // capital 'A' with diaeresis 00728 retval += 0x5b; 00729 break; 00730 case 0x00d6: // capital 'O' with diaeresis 00731 retval += 0x5c; 00732 break; 00733 case 0x00d1: // capital 'N' with tilde 00734 retval += 0x5d; 00735 break; 00736 case 0x00dc: // capital 'U' with diaeresis 00737 retval += 0x5e; 00738 break; 00739 case 0x00a7: // section sign 00740 retval += 0x5f; 00741 break; 00742 case 0x00bf: // inverted question mark 00743 retval += 0x60; 00744 break; 00745 case 0x00e4: // small 'a' with diaeresis 00746 retval += 0x7b; 00747 break; 00748 case 0x00f6: // small 'o' with diaeresis 00749 retval += 0x7c; 00750 break; 00751 case 0x00f1: // small 'n' with tilde 00752 retval += 0x7d; 00753 break; 00754 case 0x00fc: // small 'u' with diaeresis 00755 retval += 0x7e; 00756 break; 00757 case 0x00e0: // small 'a' with grave 00758 retval += 0x7f; 00759 break; 00760 } 00761 } 00762 return retval; 00763 } 00764 00765 00766 00767 /** 00768 * decodeMessage 00769 * Diese Methode konvertiert den ERICSSON Zeichensatz (SMS) in Unicode. 00770 * Parameter: QString input 00771 * Rueckgabewert: QString decodedMessage 00772 */ 00773 QString BlueConvert::decodeMessage(QString encodedMessage) 00774 { 00775 QString decodedMessage=""; 00776 unsigned char data[281]; 00777 unsigned char dec[161]; 00778 unsigned int i; 00779 int c=0; 00780 int offset; 00781 int first; 00782 int end; 00783 00784 for (i=0;i<encodedMessage.length();i+=2) 00785 { 00786 data[c] = (encodedMessage.mid(i, 2)).toInt(0,16); 00787 c++; 00788 } 00789 00790 offset = -1; 00791 c = 0; 00792 00793 for(i=0;i<m_messageLength;i++) 00794 { 00795 if (i%8) 00796 { 00797 first = data[i-1-offset]; 00798 first >>= 8 - (i % 8); 00799 end = data[i - offset]; 00800 end <<= (i % 8); 00801 *(dec + c) = (first | end) & 127; 00802 } 00803 else 00804 { 00805 ++offset; 00806 *(dec + c) = data[i - offset] & 127; 00807 } 00808 00809 if (*(dec + c) == 0) 00810 { 00811 *(dec + c) = 128; 00812 } 00813 c++; 00814 } 00815 00816 dec[c] = '\0'; 00817 00818 //Ok, 7bit message decoded, now convert to human readable signs 00819 00820 for(i=0;i<strlen((char*)dec);i++) 00821 { 00822 switch(dec[i]) 00823 { 00824 00825 case 1: 00826 decodedMessage.append("£"); 00827 break; 00828 00829 case 2: 00830 decodedMessage.append("$"); 00831 break; 00832 00833 case 3: 00834 decodedMessage.append("¥"); 00835 break; 00836 00837 case 4: 00838 decodedMessage.append("è"); 00839 break; 00840 00841 case 5: 00842 decodedMessage.append("é"); 00843 break; 00844 00845 case 6: 00846 decodedMessage.append("ù"); 00847 break; 00848 00849 case 7: 00850 decodedMessage.append("ì"); 00851 break; 00852 00853 case 8: 00854 decodedMessage.append("ò"); 00855 break; 00856 00857 case 9: 00858 decodedMessage.append("Ç"); 00859 break; 00860 00861 case 10: 00862 //decodedMessage.append("\n"); //linefeed 00863 break; 00864 00865 case 11: 00866 decodedMessage.append("Ø"); 00867 break; 00868 00869 case 12: 00870 decodedMessage.append("ø"); 00871 break; 00872 00873 case 13: 00874 //decodedMessage.append("\r"); //carriage return 00875 break; 00876 00877 case 14: 00878 decodedMessage.append("Å"); 00879 break; 00880 00881 case 15: 00882 decodedMessage.append("å"); 00883 break; 00884 00885 case 16: 00886 //captial DELTA 00887 break; 00888 00889 case 17: 00890 decodedMessage.append("_"); 00891 break; 00892 00893 case 18: 00894 //captial PHI 00895 break; 00896 00897 case 19: 00898 //captial GAMMA 00899 break; 00900 00901 case 20: 00902 //captial LAMBDA 00903 break; 00904 00905 case 21: 00906 //captial OMEGA 00907 break; 00908 00909 case 22: 00910 //captial PI 00911 break; 00912 00913 case 23: 00914 //captial PSI 00915 break; 00916 00917 case 24: 00918 //captial SIGMA 00919 break; 00920 00921 case 25: 00922 //captial THETA 00923 break; 00924 00925 case 26: 00926 //captial XI 00927 break; 00928 00929 case 27: //escape to extension table 00930 i++; 00931 switch (dec[i]) 00932 { 00933 case 10: 00934 //form feed 00935 break; 00936 00937 case 20: 00938 decodedMessage.append("^"); 00939 break; 00940 00941 case 40: 00942 decodedMessage.append("{"); 00943 break; 00944 00945 case 41: 00946 decodedMessage.append("}"); 00947 break; 00948 00949 case 47: 00950 decodedMessage.append("\\"); 00951 break; 00952 00953 case 60: 00954 decodedMessage.append("["); 00955 break; 00956 00957 case 61: 00958 decodedMessage.append("~"); 00959 break; 00960 00961 case 62: 00962 decodedMessage.append("]"); 00963 break; 00964 00965 case 64: 00966 decodedMessage.append("|"); 00967 break; 00968 00969 case 101: 00970 //EURO SIGN decodedMessage.append(""); 00971 break; 00972 } 00973 break; 00974 00975 case 28: 00976 decodedMessage.append("Æ"); 00977 break; 00978 00979 case 29: 00980 decodedMessage.append("æ"); 00981 break; 00982 00983 case 30: 00984 decodedMessage.append("ß"); 00985 break; 00986 00987 case 31: 00988 decodedMessage.append("É"); 00989 break; 00990 00991 case 32: 00992 decodedMessage.append(" "); 00993 break; 00994 00995 case 33: 00996 decodedMessage.append("!"); 00997 break; 00998 00999 case 34: 01000 decodedMessage.append("\""); 01001 break; 01002 01003 case 35: 01004 decodedMessage.append("#"); 01005 break; 01006 01007 case 36: 01008 //currency sign decodedMessage.append(""); 01009 break; 01010 01011 case 37: 01012 decodedMessage.append("%"); 01013 break; 01014 01015 case 38: 01016 decodedMessage.append("&"); 01017 break; 01018 01019 case 39: 01020 decodedMessage.append("'"); 01021 break; 01022 01023 case 40: 01024 decodedMessage.append("("); 01025 break; 01026 01027 case 41: 01028 decodedMessage.append(")"); 01029 break; 01030 01031 case 42: 01032 decodedMessage.append("*"); 01033 break; 01034 01035 case 43: 01036 decodedMessage.append("+"); 01037 break; 01038 01039 case 44: 01040 decodedMessage.append(","); 01041 break; 01042 01043 case 45: 01044 decodedMessage.append("-"); 01045 break; 01046 01047 case 46: 01048 decodedMessage.append("."); 01049 break; 01050 01051 case 47: 01052 decodedMessage.append("/"); 01053 break; 01054 01055 case 48: 01056 decodedMessage.append("0"); 01057 break; 01058 01059 case 49: 01060 decodedMessage.append("1"); 01061 break; 01062 01063 case 50: 01064 decodedMessage.append("2"); 01065 break; 01066 01067 case 51: 01068 decodedMessage.append("3"); 01069 break; 01070 01071 case 52: 01072 decodedMessage.append("4"); 01073 break; 01074 01075 case 53: 01076 decodedMessage.append("5"); 01077 break; 01078 01079 case 54: 01080 decodedMessage.append("6"); 01081 break; 01082 01083 case 55: 01084 decodedMessage.append("7"); 01085 break; 01086 01087 case 56: 01088 decodedMessage.append("8"); 01089 break; 01090 01091 case 57: 01092 decodedMessage.append("9"); 01093 break; 01094 01095 case 58: 01096 decodedMessage.append(":"); 01097 break; 01098 01099 case 59: 01100 decodedMessage.append(";"); 01101 break; 01102 01103 case 60: 01104 decodedMessage.append("<"); 01105 break; 01106 01107 case 61: 01108 decodedMessage.append("="); 01109 break; 01110 01111 case 62: 01112 decodedMessage.append(">"); 01113 break; 01114 01115 case 63: 01116 decodedMessage.append("?"); 01117 break; 01118 01119 case 64: 01120 decodedMessage.append("¡"); 01121 break; 01122 01123 case 65: 01124 decodedMessage.append("A"); 01125 break; 01126 01127 case 66: 01128 decodedMessage.append("B"); 01129 break; 01130 01131 case 67: 01132 decodedMessage.append("C"); 01133 break; 01134 01135 case 68: 01136 decodedMessage.append("D"); 01137 break; 01138 01139 case 69: 01140 decodedMessage.append("E"); 01141 break; 01142 01143 case 70: 01144 decodedMessage.append("F"); 01145 break; 01146 01147 case 71: 01148 decodedMessage.append("G"); 01149 break; 01150 01151 case 72: 01152 decodedMessage.append("H"); 01153 break; 01154 01155 case 73: 01156 decodedMessage.append("I"); 01157 break; 01158 01159 case 74: 01160 decodedMessage.append("J"); 01161 break; 01162 01163 case 75: 01164 decodedMessage.append("K"); 01165 break; 01166 01167 case 76: 01168 decodedMessage.append("L"); 01169 break; 01170 01171 case 77: 01172 decodedMessage.append("M"); 01173 break; 01174 01175 case 78: 01176 decodedMessage.append("N"); 01177 break; 01178 01179 case 79: 01180 decodedMessage.append("O"); 01181 break; 01182 01183 case 80: 01184 decodedMessage.append("P"); 01185 break; 01186 01187 case 81: 01188 decodedMessage.append("Q"); 01189 break; 01190 01191 case 82: 01192 decodedMessage.append("R"); 01193 break; 01194 01195 case 83: 01196 decodedMessage.append("S"); 01197 break; 01198 01199 case 84: 01200 decodedMessage.append("T"); 01201 break; 01202 01203 case 85: 01204 decodedMessage.append("U"); 01205 break; 01206 01207 case 86: 01208 decodedMessage.append("V"); 01209 break; 01210 01211 case 87: 01212 decodedMessage.append("W"); 01213 break; 01214 01215 case 88: 01216 decodedMessage.append("X"); 01217 break; 01218 01219 case 89: 01220 decodedMessage.append("Y"); 01221 break; 01222 01223 case 90: 01224 decodedMessage.append("Z"); 01225 break; 01226 01227 case 91: 01228 decodedMessage.append("Ä"); 01229 break; 01230 01231 case 92: 01232 decodedMessage.append("Ö"); 01233 break; 01234 01235 case 93: 01236 decodedMessage.append("Ñ"); 01237 break; 01238 01239 case 94: 01240 decodedMessage.append("Ü"); 01241 break; 01242 01243 case 95: 01244 decodedMessage.append("§"); 01245 break; 01246 01247 case 96: 01248 decodedMessage.append("¿"); 01249 break; 01250 01251 case 97: 01252 decodedMessage.append("a"); 01253 break; 01254 01255 case 98: 01256 decodedMessage.append("b"); 01257 break; 01258 01259 case 99: 01260 decodedMessage.append("c"); 01261 break; 01262 01263 case 100: 01264 decodedMessage.append("d"); 01265 break; 01266 01267 case 101: 01268 decodedMessage.append("e"); 01269 break; 01270 01271 case 102: 01272 decodedMessage.append("f"); 01273 break; 01274 01275 case 103: 01276 decodedMessage.append("g"); 01277 break; 01278 01279 case 104: 01280 decodedMessage.append("h"); 01281 break; 01282 01283 case 105: 01284 decodedMessage.append("i"); 01285 break; 01286 01287 case 106: 01288 decodedMessage.append("j"); 01289 break; 01290 01291 case 107: 01292 decodedMessage.append("k"); 01293 break; 01294 01295 case 108: 01296 decodedMessage.append("l"); 01297 break; 01298 01299 case 109: 01300 decodedMessage.append("m"); 01301 break; 01302 01303 case 110: 01304 decodedMessage.append("n"); 01305 break; 01306 01307 case 111: 01308 decodedMessage.append("o"); 01309 break; 01310 01311 case 112: 01312 decodedMessage.append("p"); 01313 break; 01314 01315 case 113: 01316 decodedMessage.append("q"); 01317 break; 01318 01319 case 114: 01320 decodedMessage.append("r"); 01321 break; 01322 01323 case 115: 01324 decodedMessage.append("s"); 01325 break; 01326 01327 case 116: 01328 decodedMessage.append("t"); 01329 break; 01330 01331 case 117: 01332 decodedMessage.append("u"); 01333 break; 01334 01335 case 118: 01336 decodedMessage.append("v"); 01337 break; 01338 01339 case 119: 01340 decodedMessage.append("w"); 01341 break; 01342 01343 case 120: 01344 decodedMessage.append("x"); 01345 break; 01346 01347 case 121: 01348 decodedMessage.append("y"); 01349 break; 01350 01351 case 122: 01352 decodedMessage.append("z"); 01353 break; 01354 01355 case 123: 01356 decodedMessage.append("ä"); 01357 break; 01358 01359 case 124: 01360 decodedMessage.append("ö"); 01361 break; 01362 01363 case 125: 01364 decodedMessage.append("ñ"); 01365 break; 01366 01367 case 126: 01368 decodedMessage.append("ü"); 01369 break; 01370 01371 case 127: 01372 decodedMessage.append("à"); 01373 break; 01374 01375 case 128: 01376 decodedMessage.append("@"); 01377 break; 01378 01379 default: 01380 break; 01381 } 01382 } 01383 return decodedMessage; 01384 } 01385 01386 01387 01388 /** 01389 * encodeMessage 01390 * Diese Methode konvertiert Unicode in den ERICSSON Zeichensatz (SMS). 01391 * Parameter: QString input, int Length 01392 * Rueckgabewert: QString encodedMessage 01393 */ 01394 QString BlueConvert::encodeMessage(QString decodedMessage, int longMessage) 01395 { 01396 QString encodedMessage =""; 01397 QString num; 01398 unsigned char enc[281]; 01399 int first, end; 01400 unsigned int i; 01401 01402 m_messageLength = decodedMessage.length(); 01403 01404 for (i=0;i<decodedMessage.length();i++) 01405 { 01406 switch(decodedMessage.at(i).latin1()) 01407 { 01408 01409 case '£': 01410 enc[i] = 0x01; 01411 break; 01412 01413 case '$': 01414 enc[i] = 0x02; 01415 break; 01416 01417 case '¥': 01418 enc[i] = 3; 01419 break; 01420 01421 case 'è': 01422 enc[i] = 4; 01423 break; 01424 01425 case 'é': 01426 enc[i] = 5; 01427 break; 01428 01429 case 'ù': 01430 enc[i] = 6; 01431 break; 01432 01433 case 'ì': 01434 enc[i] = 7; 01435 break; 01436 01437 case 'ò': 01438 enc[i] = 8; 01439 break; 01440 01441 case 'Ç': 01442 enc[i] = 9; 01443 break; 01444 01445 case '\n': 01446 enc[i] = 10; 01447 break; 01448 01449 case 'Ø': 01450 enc[i] = 11; 01451 break; 01452 01453 case 'ø': 01454 enc[i] = 12; 01455 break; 01456 01457 case '\r': 01458 enc[i] = 13; 01459 break; 01460 01461 case 'Å': 01462 enc[i] = 14; 01463 break; 01464 01465 case 'å': 01466 enc[i] = 15; 01467 break; 01468 01469 /*case capital DELTA: 01470 enc[i] = 16; 01471 break; */ 01472 01473 case '_': 01474 enc[i] = 17; 01475 break; 01476 01477 01478 /* GREEK ALPHABET 01479 case 01480 enc[i] = 18; 01481 break; 01482 01483 case '£': 01484 enc[i] = 19; 01485 break; 01486 01487 case '£': 01488 enc[i] = 21; 01489 break; 01490 01491 case '£': 01492 enc[i] = 22; 01493 break; 01494 01495 case '£': 01496 enc[i] = 23; 01497 break; 01498 01499 case '£': 01500 enc[i] = 24; 01501 break; 01502 01503 case '£': 01504 enc[i] = 25; 01505 break; 01506 01507 case '£': 01508 enc[i] = 26; 01509 break; 01510 */ 01511 case '^': 01512 enc[i] = 27; 01513 i++; 01514 enc[i] = 20; 01515 break; 01516 01517 case '{': 01518 enc[i] = 27; 01519 i++; 01520 enc[i] = 40; 01521 break; 01522 01523 case '}': 01524 enc[i] = 27; 01525 i++; 01526 enc[i] = 41; 01527 break; 01528 01529 case '\\': 01530 enc[i] = 27; 01531 i++; 01532 enc[i] = 47; 01533 break; 01534 01535 case '[': 01536 enc[i] = 27; 01537 i++; 01538 enc[i] = 60; 01539 break; 01540 01541 case '~': 01542 enc[i] = 27; 01543 i++; 01544 enc[i] = 61; 01545 break; 01546 01547 case ']': 01548 enc[i] = 27; 01549 i++; 01550 enc[i] = 62; 01551 break; 01552 01553 case '|': 01554 enc[i] = 27; 01555 i++; 01556 enc[i] = 64; 01557 break; 01558 01559 /*EURO SIGN case '': 01560 enc[i] = 27; 01561 i++; 01562 enc[i] = 40; 01563 break; */ 01564 01565 case 'Æ': 01566 enc[i] = 28; 01567 break; 01568 01569 case 'æ': 01570 enc[i] = 29; 01571 break; 01572 01573 case 'ß': 01574 enc[i] = 30; 01575 break; 01576 01577 case 'É': 01578 enc[i] = 31; 01579 break; 01580 01581 case ' ': 01582 enc[i] = 32; 01583 break; 01584 01585 case '!': 01586 enc[i] = 33; 01587 break; 01588 01589 case '"': 01590 enc[i] = 34; 01591 break; 01592 01593 case '#': 01594 enc[i] = 35; 01595 break; 01596 01597 //CURRENCY SIGN 01598 01599 01600 case '%': 01601 enc[i] = 37; 01602 break; 01603 01604 case '&': 01605 enc[i] = 38; 01606 break; 01607 01608 case '\'': 01609 enc[i] = 39; 01610 break; 01611 01612 case '(': 01613 enc[i] = 40; 01614 break; 01615 01616 case ')': 01617 enc[i] = 41; 01618 break; 01619 01620 case '*': 01621 enc[i] = 42; 01622 break; 01623 01624 case '+': 01625 enc[i] = 43; 01626 break; 01627 01628 case ',': 01629 enc[i] = 44; 01630 break; 01631 01632 case '-': 01633 enc[i] = 45; 01634 break; 01635 01636 case '.': 01637 enc[i] = 46; 01638 break; 01639 01640 case '/': 01641 enc[i] = 47; 01642 break; 01643 01644 case '0': 01645 enc[i] = 48; 01646 break; 01647 01648 case '1': 01649 enc[i] = 49; 01650 break; 01651 01652 case '2': 01653 enc[i] = 50; 01654 break; 01655 01656 case '3': 01657 enc[i] = 51; 01658 break; 01659 01660 case '4': 01661 enc[i] = 52; 01662 break; 01663 01664 case '5': 01665 enc[i] = 53; 01666 break; 01667 01668 case '6': 01669 enc[i] = 54; 01670 break; 01671 01672 case '7': 01673 enc[i] = 55; 01674 break; 01675 01676 case '8': 01677 enc[i] = 56; 01678 break; 01679 01680 case '9': 01681 enc[i] = 57; 01682 break; 01683 01684 case ':': 01685 enc[i] = 58; 01686 break; 01687 01688 case ';': 01689 enc[i] = 59; 01690 break; 01691 01692 case '<': 01693 enc[i] = 60; 01694 break; 01695 01696 case '=': 01697 enc[i] = 61; 01698 break; 01699 01700 case '>': 01701 enc[i] = 62; 01702 break; 01703 01704 case '?': 01705 enc[i] = 63; 01706 break; 01707 01708 case '¡': 01709 enc[i] = 64; 01710 break; 01711 01712 case 'A': 01713 enc[i] = 65; 01714 break; 01715 01716 case 'B': 01717 enc[i] = 66; 01718 break; 01719 01720 case 'C': 01721 enc[i] = 67; 01722 break; 01723 01724 case 'D': 01725 enc[i] = 68; 01726 break; 01727 01728 case 'E': 01729 enc[i] = 69; 01730 break; 01731 01732 case 'F': 01733 enc[i] = 70; 01734 break; 01735 01736 case 'G': 01737 enc[i] = 71; 01738 break; 01739 01740 case 'H': 01741 enc[i] = 72; 01742 break; 01743 01744 case 'I': 01745 enc[i] = 73; 01746 break; 01747 01748 case 'J': 01749 enc[i] = 74; 01750 break; 01751 01752 case 'K': 01753 enc[i] = 75; 01754 break; 01755 01756 case 'L': 01757 enc[i] = 76; 01758 break; 01759 01760 case 'M': 01761 enc[i] = 77; 01762 break; 01763 01764 case 'N': 01765 enc[i] = 78; 01766 break; 01767 01768 case 'O': 01769 enc[i] = 79; 01770 break; 01771 01772 case 'P': 01773 enc[i] = 80; 01774 break; 01775 01776 case 'Q': 01777 enc[i] = 81; 01778 break; 01779 01780 case 'R': 01781 enc[i] = 82; 01782 break; 01783 01784 case 'S': 01785 enc[i] = 83; 01786 break; 01787 01788 case 'T': 01789 enc[i] = 84; 01790 break; 01791 01792 case 'U': 01793 enc[i] = 85; 01794 break; 01795 01796 case 'V': 01797 enc[i] = 86; 01798 break; 01799 01800 case 'W': 01801 enc[i] = 87; 01802 break; 01803 01804 case 'X': 01805 enc[i] = 88; 01806 break; 01807 01808 case 'Y': 01809 enc[i] = 89; 01810 break; 01811 01812 case 'Z': 01813 enc[i] = 90; 01814 break; 01815 01816 case 'Ä': 01817 enc[i] = 91; 01818 break; 01819 01820 case 'Ö': 01821 enc[i] = 92; 01822 break; 01823 01824 case 'Ñ': 01825 enc[i] = 93; 01826 break; 01827 01828 case 'Ü': 01829 enc[i] = 94; 01830 break; 01831 01832 case '§': 01833 enc[i] = 95; 01834 break; 01835 01836 case '¿': 01837 enc[i] = 96; 01838 break; 01839 01840 case 'a': 01841 enc[i] = 97; 01842 break; 01843 01844 case 'b': 01845 enc[i] = 98; 01846 break; 01847 01848 case 'c': 01849 enc[i] = 99; 01850 break; 01851 01852 case 'd': 01853 enc[i] = 100; 01854 break; 01855 01856 case 'e': 01857 enc[i] = 101; 01858 break; 01859 01860 case 'f': 01861 enc[i] = 102; 01862 break; 01863 01864 case 'g': 01865 enc[i] = 103; 01866 break; 01867 01868 case 'h': 01869 enc[i] = 104; 01870 break; 01871 01872 case 'i': 01873 enc[i] = 105; 01874 break; 01875 01876 case 'j': 01877 enc[i] = 106; 01878 break; 01879 01880 case 'k': 01881 enc[i] = 107; 01882 break; 01883 01884 case 'l': 01885 enc[i] = 108; 01886 break; 01887 01888 case 'm': 01889 enc[i] = 109; 01890 break; 01891 01892 case 'n': 01893 enc[i] = 110; 01894 break; 01895 01896 case 'o': 01897 enc[i] = 111; 01898 break; 01899 01900 case 'p': 01901 enc[i] = 112; 01902 break; 01903 01904 case 'q': 01905 enc[i] = 113; 01906 break; 01907 01908 case 'r': 01909 enc[i] = 114; 01910 break; 01911 01912 case 's': 01913 enc[i] = 115; 01914 break; 01915 01916 case 't': 01917 enc[i] = 116; 01918 break; 01919 01920 case 'u': 01921 enc[i] = 117; 01922 break; 01923 01924 case 'v': 01925 enc[i] = 118; 01926 break; 01927 01928 case 'w': 01929 enc[i] = 119; 01930 break; 01931 01932 case 'x': 01933 enc[i] = 120; 01934 break; 01935 01936 case 'y': 01937 enc[i] = 121; 01938 break; 01939 01940 case 'z': 01941 enc[i] = 122; 01942 break; 01943 01944 case 'ä': 01945 enc[i] = 123; 01946 break; 01947 01948 case 'ö': 01949 enc[i] = 124; 01950 break; 01951 01952 case 'ñ': 01953 enc[i] = 125; 01954 break; 01955 01956 case 'ü': 01957 enc[i] = 126; 01958 break; 01959 01960 case 'à': 01961 enc[i] = 127; 01962 break; 01963 01964 case '@': 01965 enc[i] = 128; 01966 break; 01967 01968 default: 01969 break; 01970 } 01971 } 01972 01973 enc[i] = '\0'; 01974 01975 //Now, we have to encode the message to its 7bit representation 01976 for (i=0; i<strlen((char*)enc); i++) 01977 { 01978 if (i==0 && longMessage) // special treatnmen - would "normally" be skipped since %8==7 01979 { 01980 first=(enc[0]&127)<<1; 01981 num.setNum(first, 16); 01982 if (first < 16) 01983 encodedMessage.append("0"); 01984 encodedMessage.append(num); 01985 } 01986 else 01987 { 01988 end = enc[i] & 127; 01989 end >>= ((i-longMessage) % 8); 01990 first = enc[i+1] & 127; 01991 first <<= 7 - ((i-longMessage) % 8); 01992 first &= 255; 01993 num.setNum((first|end), 16); 01994 if ((first|end) < 16) 01995 encodedMessage.append("0"); 01996 encodedMessage.append(num); 01997 if (((i-longMessage) % 8) == 6) 01998 i++; 01999 } 02000 } 02001 return encodedMessage; 02002 } 02003 02004 02005

Generated on Tue Aug 17 14:42:25 2004 for BluePhone by doxygen 1.3.7