Ticket #1591: openmoko-dialer2-sms-7bit-code-properly.patch

File openmoko-dialer2-sms-7bit-code-properly.patch, 12.2 KB (added by stiell, 11 years ago)

Encode and decode 7-bit messages properly.

  • OM-2007.2/applications/openmoko-dialer2/src/phone-kit/moko-sms.c

    old new on_incoming_sms (MokoListener *listener, 
    288288  message = NULL; 
    289289  switch (sms->payload.coding_scheme) { 
    290290  case ALPHABET_DEFAULT : 
    291     g_debug ("Decoding 7-bit ASCII message:"); 
    292     message = g_malloc0 (GSMD_SMS_DATA_MAXLEN); 
    293     unpacking_7bit_character (&sms->payload, message); 
    294     break; 
     291    { 
     292      gint i; 
     293      gint l; 
     294      gchar *gsmdefault; 
     295      gchar *dest; 
     296      g_debug ("Decoding GSM 7-bit default alphabet message:"); 
     297      gsmdefault = g_malloc0 (GSMD_SMS_DATA_MAXLEN + 1); 
     298      l = unpacking_7bit_character (&sms->payload, gsmdefault); 
     299      message = g_malloc0 (1 + 3 * l); 
     300      dest = message; 
     301      for (i = 0; i < l; i++) { 
     302        /* Decoding based on the mapping at 
     303         * http://unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT 
     304         */ 
     305        switch (gsmdefault[i]) { 
     306        case 0x00: // COMMERCIAL AT 
     307          *(dest++) = '@'; break; 
     308        case 0x01: // POUND SIGN 
     309          *(dest++) = 0xc2; *(dest++) = 0xa3; break; 
     310        case 0x02: // DOLLAR SIGN 
     311          *(dest++) = '$'; break; 
     312        case 0x03: // YEN SIGN 
     313          *(dest++) = 0xc2; *(dest++) = 0xa5; break; 
     314        case 0x04: // LATIN SMALL LETTER E WITH GRAVE 
     315          *(dest++) = 0xc3; *(dest++) = 0xa8; break; 
     316        case 0x05: // LATIN SMALL LETTER E WITH ACUTE 
     317          *(dest++) = 0xc3; *(dest++) = 0xa9; break; 
     318        case 0x06: // LATIN SMALL LETTER U WITH GRAVE 
     319          *(dest++) = 0xc3; *(dest++) = 0xb9; break; 
     320        case 0x07: // LATIN SMALL LETTER I WITH GRAVE 
     321          *(dest++) = 0xc3; *(dest++) = 0xac; break; 
     322        case 0x08: // LATIN SMALL LETTER O WITH GRAVE 
     323          *(dest++) = 0xc3; *(dest++) = 0xb2; break; 
     324        case 0x09: // LATIN SMALL LETTER C WITH CEDILLA 
     325          *(dest++) = 0xc3; *(dest++) = 0xa7; break; 
     326        case 0x0b: // LATIN CAPITAL LETTER O WITH STROKE 
     327          *(dest++) = 0xc3; *(dest++) = 0x98; break; 
     328        case 0x0c: // LATIN SMALL LETTER O WITH STROKE 
     329          *(dest++) = 0xc3; *(dest++) = 0xb8; break; 
     330        case 0x0e: // LATIN CAPITAL LETTER A WITH RING ABOVE 
     331          *(dest++) = 0xc3; *(dest++) = 0x85; break; 
     332        case 0x0f: // LATIN SMALL LETTER A WITH RING ABOVE 
     333          *(dest++) = 0xc3; *(dest++) = 0xa5; break; 
     334        case 0x10: // GREEK CAPITAL LETTER DELTA 
     335          *(dest++) = 0xce; *(dest++) = 0x94; break; 
     336        case 0x11: // LOW LINE 
     337          *(dest++) = '_'; break; 
     338        case 0x12: // GREEK CAPITAL LETTER PHI 
     339          *(dest++) = 0xce; *(dest++) = 0xa6; break; 
     340        case 0x13: // GREEK CAPITAL LETTER GAMMA 
     341          *(dest++) = 0xce; *(dest++) = 0x93; break; 
     342        case 0x14: // GREEK CAPITAL LETTER LAMDA 
     343          *(dest++) = 0xce; *(dest++) = 0x9b; break; 
     344        case 0x15: // GREEK CAPITAL LETTER OMEGA 
     345          *(dest++) = 0xce; *(dest++) = 0xa9; break; 
     346        case 0x16: // GREEK CAPITAL LETTER PI 
     347          *(dest++) = 0xce; *(dest++) = 0xa0; break; 
     348        case 0x17: // GREEK CAPITAL LETTER PSI 
     349          *(dest++) = 0xce; *(dest++) = 0xa8; break; 
     350        case 0x18: // GREEK CAPITAL LETTER SIGMA 
     351          *(dest++) = 0xce; *(dest++) = 0xa3; break; 
     352        case 0x19: // GREEK CAPITAL LETTER THETA 
     353          *(dest++) = 0xce; *(dest++) = 0x98; break; 
     354        case 0x1a: // GREEK CAPITAL LETTER XI 
     355          *(dest++) = 0xce; *(dest++) = 0x9e; break; 
     356        case 0x1b: // Escape character 
     357          switch (gsmdefault[++i]) { 
     358          case 0x0a: // FORM FEED 
     359            *(dest++) = 0x0c; break; 
     360          case 0x14: // CIRCUMFLEX ACCENT 
     361            *(dest++) = '^'; break; 
     362          case 0x28: // LEFT CURLY BRACKET 
     363            *(dest++) = '{'; break; 
     364          case 0x29: // RIGHT CURLY BRACKET 
     365            *(dest++) = '}'; break; 
     366          case 0x2f: // REVERSE SOLIDUS 
     367            *(dest++) = '\\'; break; 
     368          case 0x3c: // LEFT SQUARE BRACKET 
     369            *(dest++) = '['; break; 
     370          case 0x3d: // TILDE 
     371            *(dest++) = '~'; break; 
     372          case 0x3e: // RIGHT SQUARE BRACKET 
     373            *(dest++) = ']'; break; 
     374          case 0x40: // VERTICAL LINE 
     375            *(dest++) = '|'; break; 
     376          case 0x65: // EURO SIGN 
     377            *(dest++) = 0xe2; *(dest++) = 0x82; 
     378            *(dest++) = 0xac; break; 
     379          default: // NBSP (for compatibility) 
     380            *(dest++) = 0xc2; *(dest++) = 0xa0; 
     381            i--; // Do not consume next character 
     382          } 
     383          break; 
     384        case 0x1c: // LATIN CAPITAL LETTER AE 
     385          *(dest++) = 0xc3; *(dest++) = 0x86; break; 
     386        case 0x1d: // LATIN SMALL LETTER AE 
     387          *(dest++) = 0xc3; *(dest++) = 0xa6; break; 
     388        case 0x1e: // LATIN SMALL LETTER SHARP S 
     389          *(dest++) = 0xc3; *(dest++) = 0x9f; break; 
     390        case 0x1f: // LATIN CAPITAL LETTER E WITH ACUTE 
     391          *(dest++) = 0xc3; *(dest++) = 0x89; break; 
     392        case 0x24: // CURRENCY SIGN 
     393          *(dest++) = 0xc2; *(dest++) = 0xa4; break; 
     394        case 0x40: // INVERTED EXCLAMATION MARK 
     395          *(dest++) = 0xc2; *(dest++) = 0xa1; break; 
     396        case 0x5b: // LATIN CAPITAL LETTER A WITH DIAERESIS 
     397          *(dest++) = 0xc3; *(dest++) = 0x84; break; 
     398        case 0x5c: // LATIN CAPITAL LETTER O WITH DIAERESIS 
     399          *(dest++) = 0xc3; *(dest++) = 0x96; break; 
     400        case 0x5d: // LATIN CAPITAL LETTER N WITH TILDE 
     401          *(dest++) = 0xc3; *(dest++) = 0x91; break; 
     402        case 0x5e: // LATIN CAPITAL LETTER U WITH DIAERESIS 
     403          *(dest++) = 0xc3; *(dest++) = 0x9c; break; 
     404        case 0x5f: // SECTION SIGN 
     405          *(dest++) = 0xc2; *(dest++) = 0xa7; break; 
     406        case 0x60: // INVERTED QUESTION MARK 
     407          *(dest++) = 0xc2; *(dest++) = 0xbf; break; 
     408        case 0x7b: // LATIN SMALL LETTER A WITH DIAERESIS 
     409          *(dest++) = 0xc3; *(dest++) = 0xa4; break; 
     410        case 0x7c: // LATIN SMALL LETTER O WITH DIAERESIS 
     411          *(dest++) = 0xc3; *(dest++) = 0xb6; break; 
     412        case 0x7d: // LATIN SMALL LETTER N WITH TILDE 
     413          *(dest++) = 0xc3; *(dest++) = 0xb1; break; 
     414        case 0x7e: // LATIN SMALL LETTER U WITH DIAERESIS 
     415          *(dest++) = 0xc3; *(dest++) = 0xbc; break; 
     416        case 0x7f: // LATIN SMALL LETTER A WITH GRAVE 
     417          *(dest++) = 0xc3; *(dest++) = 0xa0; break; 
     418        default: // Untranslated 
     419          *(dest++) = gsmdefault[i]; 
     420        } 
     421      } 
     422      g_free (gsmdefault); 
     423      break; 
     424    } 
    295425  case ALPHABET_8BIT : 
    296426    /* TODO: Verify: Is this encoding just UTF-8? (it is on my Samsung phone) */ 
    297427    g_debug ("Decoding UTF-8 message:"); 
    moko_sms_send (MokoSms *self, const gcha 
    744874  MokoSmsPrivate *priv; 
    745875  struct lgsm_sms sms; 
    746876  gint msg_length, c; 
    747   gboolean ascii; 
     877  glong  msg16_length; 
     878  gboolean gsm7bit; 
    748879  JanaNote *note; 
    749880  gchar *dialcode = NULL; 
    750881  gchar *sub_num = NULL; 
     882  gunichar2 *message16; 
    751883   
    752884  g_assert (self && number && message); 
    753885  priv = self->priv; 
    moko_sms_send (MokoSms *self, const gcha 
    782914  } else { 
    783915    strcpy (sms.addr, number); 
    784916  } 
    785    
    786917  /* Set message */ 
    787   /* Check if the text is ascii (and pack in 7 bits if so) */ 
    788   ascii = TRUE; 
    789   for (c = 0; message[c] != '\0'; c++) { 
    790     if (((guint8)message[c]) > 0x7F) { 
    791       ascii = FALSE; 
    792       break; 
    793     } 
    794   } 
     918  /* Try to encode to the 7-bit default alphabet, fall back to UTF-8 */ 
     919  message16 = g_utf8_to_utf16 (message, -1, NULL, &msg16_length, NULL); 
     920  gsm7bit = TRUE; 
    795921   
    796922  /* TODO: Multi-part messages using UDH */ 
    797923  msg_length = strlen (message); 
    798   if ((ascii && (msg_length > 160)) || (msg_length > 140)) { 
     924  gchar *smschars = g_malloc0 (162); 
     925  gint i = 0; 
     926  for (c = 0; c < msg16_length; c++) { 
     927    /* See http://unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT for details */ 
     928    switch (message16[c]) { 
     929    case 0x000c: smschars[i++] = 0x1b; smschars[i++] = 0x0a; break; 
     930    case 0x0024: smschars[i++] = 0x02; break; 
     931    /* HACK: 0x80 instead of 0x00, avoids string termination */ 
     932    case 0x0040: smschars[i++] = 0x80; break; 
     933    case 0x005b: smschars[i++] = 0x1b; smschars[i++] = 0x3c; break; 
     934    case 0x005c: smschars[i++] = 0x1b; smschars[i++] = 0x2f; break; 
     935    case 0x005d: smschars[i++] = 0x1b; smschars[i++] = 0x3e; break; 
     936    case 0x005e: smschars[i++] = 0x1b; smschars[i++] = 0x14; break; 
     937    case 0x005f: smschars[i++] = 0x11; break; 
     938    case 0x007b: smschars[i++] = 0x1b; smschars[i++] = 0x28; break; 
     939    case 0x007c: smschars[i++] = 0x1b; smschars[i++] = 0x40; break; 
     940    case 0x007d: smschars[i++] = 0x1b; smschars[i++] = 0x29; break; 
     941    case 0x007e: smschars[i++] = 0x1b; smschars[i++] = 0x3d; break; 
     942    case 0x00a1: smschars[i++] = 0x40; break; 
     943    case 0x00a3: smschars[i++] = 0x01; break; 
     944    case 0x00a4: smschars[i++] = 0x24; break; 
     945    case 0x00a5: smschars[i++] = 0x03; break; 
     946    case 0x00a7: smschars[i++] = 0x5f; break; 
     947    case 0x00bf: smschars[i++] = 0x60; break; 
     948    case 0x00c4: smschars[i++] = 0x5b; break; 
     949    case 0x00c5: smschars[i++] = 0x0e; break; 
     950    case 0x00c6: smschars[i++] = 0x1c; break; 
     951    case 0x00c9: smschars[i++] = 0x1f; break; 
     952    case 0x00d1: smschars[i++] = 0x5d; break; 
     953    case 0x00d6: smschars[i++] = 0x5c; break; 
     954    case 0x00d8: smschars[i++] = 0x0b; break; 
     955    case 0x00dc: smschars[i++] = 0x5e; break; 
     956    case 0x00df: smschars[i++] = 0x1e; break; 
     957    case 0x00e0: smschars[i++] = 0x7f; break; 
     958    case 0x00e4: smschars[i++] = 0x7b; break; 
     959    case 0x00e5: smschars[i++] = 0x0f; break; 
     960    case 0x00e6: smschars[i++] = 0x1d; break; 
     961    case 0x00e7: smschars[i++] = 0x09; break; 
     962    case 0x00e8: smschars[i++] = 0x04; break; 
     963    case 0x00e9: smschars[i++] = 0x05; break; 
     964    case 0x00ec: smschars[i++] = 0x07; break; 
     965    case 0x00f1: smschars[i++] = 0x7d; break; 
     966    case 0x00f2: smschars[i++] = 0x08; break; 
     967    case 0x00f6: smschars[i++] = 0x7c; break; 
     968    case 0x00f8: smschars[i++] = 0x0c; break; 
     969    case 0x00f9: smschars[i++] = 0x06; break; 
     970    case 0x00fc: smschars[i++] = 0x7e; break; 
     971    /* Greek characters have the same mapping as capital Latin characters where 
     972     * they both have the same form. 
     973     */ 
     974    case 0x0391: smschars[i++] = 0x41; break; 
     975    case 0x0392: smschars[i++] = 0x42; break; 
     976    case 0x0393: smschars[i++] = 0x13; break; 
     977    case 0x0394: smschars[i++] = 0x10; break; 
     978    case 0x0395: smschars[i++] = 0x45; break; 
     979    case 0x0396: smschars[i++] = 0x5a; break; 
     980    case 0x0397: smschars[i++] = 0x48; break; 
     981    case 0x0398: smschars[i++] = 0x19; break; 
     982    case 0x0399: smschars[i++] = 0x49; break; 
     983    case 0x039a: smschars[i++] = 0x4b; break; 
     984    case 0x039b: smschars[i++] = 0x14; break; 
     985    case 0x039c: smschars[i++] = 0x4d; break; 
     986    case 0x039d: smschars[i++] = 0x4e; break; 
     987    case 0x039e: smschars[i++] = 0x1a; break; 
     988    case 0x039f: smschars[i++] = 0x4f; break; 
     989    case 0x03a0: smschars[i++] = 0x16; break; 
     990    case 0x03a1: smschars[i++] = 0x50; break; 
     991    case 0x03a3: smschars[i++] = 0x18; break; 
     992    case 0x03a4: smschars[i++] = 0x54; break; 
     993    case 0x03a5: smschars[i++] = 0x55; break; 
     994    case 0x03a6: smschars[i++] = 0x12; break; 
     995    case 0x03a7: smschars[i++] = 0x58; break; 
     996    case 0x03a8: smschars[i++] = 0x17; break; 
     997    case 0x03a9: smschars[i++] = 0x15; break; 
     998    case 0x20ac: smschars[i++] = 0x1b; smschars[i++] = 0x65; break; 
     999    default: 
     1000      { 
     1001        gunichar2 d = message16[c]; 
     1002        if (d == 0x000a || d == 0x000d || 
     1003            (d >= 0x0020 && d < 0x005b) || (d >= 0x0061 && d < 0x0080)) 
     1004          smschars[i++] = (gchar) d; 
     1005        else 
     1006          gsm7bit = FALSE; 
     1007      } 
     1008    } 
     1009    if (i > 160 || !gsm7bit) break; 
     1010  } 
     1011  if ((i > 160 && gsm7bit) || (msg_length > 140 && !gsm7bit)) { 
    7991012      *error = g_error_new (PHONE_KIT_SMS_ERROR, PK_SMS_ERROR_MSG_TOOLONG, 
    8001013                            "Message too long"); 
     1014      g_free (smschars); 
    8011015      return FALSE; 
    8021016  } 
    803   if (ascii) { 
    804     packing_7bit_character (message, &sms); 
    805   } else { 
     1017  if (gsm7bit) { 
     1018    packing_7bit_character (smschars, &sms); 
     1019  } 
     1020  else { 
    8061021    sms.alpha = ALPHABET_8BIT; 
    8071022    strcpy ((gchar *)sms.data, message); 
     1023    sms.length = msg_length; 
    8081024  } 
    809   sms.length = msg_length; 
     1025  g_free (smschars); 
    8101026   
    8111027  /* Send message */ 
    8121028  lgsm_sms_send (handle, &sms);