'Güvenilir' SMS Unicode &

5 Cevap php

(Updated a little)

Ben çok PHP kullanarak uluslararasılaşma ile deneyimli değilim, bunun söylenmesi gerekir, ve arama bir anlaşma gerçekten ben aradığım cevaplar vermedi.

Ben (bir hizmet C # kullanarak yazılabilir iken, sadece geçici olarak) PHP kullanarak bir SMS mesajı göndermek için Unicode için sadece 'uygun' metni dönüştürmek için güvenilir bir yol çalışma dışarı ihtiyacı kulüpler - Açıkçası, şu anda gönderilen mesajlardır düz metin olarak gönderilir.

(Standart GSM charset kullanarak karşı) ben makul Unicode karakter kümesine her şeyi dönüştürmek olabilir, ama bu all mesajları (yerine 160) 70 karakter ile sınırlı olacağı anlamına gelecektir.

Yani, benim asıl soru sanırım: what is the most reliable way to detect the requirement for a message to be Unicode-encoded, so I only have to do it when it's absolutely necessary (e.g. for non-Latin-language characters)?

Added Info:

Tamam, ben bunun üzerinde çalışıyoruz sabah geçirdim, ve (bu dönüşüm charset geldiğinde nedeniyle yetkinlik eksikliği tamamlamak için kesinlikle) Ben başladığımda başka üzerinde daha hala yaşıyorum. Yani burada revize senaryo:

Ben metin SMS mesajları harici bir kaynaktan geliyor olması, bu dış kaynak düz metin + unicode çizgi-kaçtı karakter bana yanıtlar sağlar. Örneğin 'görünür' metni:

En OAU EAE אין תמיכה בעברית test edelim

İade:

En \ u00f6 \ u00e4 \ u00fc \ u00E9 \ u00e0 \ u00e8 \ u05d0 \ u05d9 \ u05df \ u05ea \ u05de \ u05d9 \ u05db \ u05d4 \ u05d1 \ u05e2 \ u05d1 \ u05e8 \ u05d9 \ u05ea test edelim

Şimdi, ben, düz metin olarak benim SMS sağlayıcı GSM 03,38 veya Unicode gönderebilir. Açıkçası, eksik karakterleri bir çok düz metin sonuçları (onlar benim sağlayıcısı tarafından boşluklarla yerini konum) gibi yukarıdaki gönderme - Ben orada ne içeriği ile ilgili uyum gerekir. I do bu ile istediğiniz ne takip ediyor:

  1. Tüm metin içinde ise olduğu gibi-GSM 03.38 codepage, gönderin. (Bu kategori içine oturması üzerinde, Ibranice karakterlere Tüm ama ancak dönüştürülmesi gerekir.)

  2. Aksi takdirde, Unicode dönüştürmek, ve (Unicode sınır her bir SMS için 70 karakter değil 160 gibi) birden fazla mesaj olarak göndereceğim.

Yukarıda söylediğim gibi, burada, ben (C # nedeniyle yerleşik bazı basit dönüştürme işlevlerine bir çok sorunu değildi) PHP bu yapmaya Stumped değilim, ama ben sadece bariz eksik oldukça muhtemel bulunuyor. Ben de, PHP 7-bit kodlama için önceden yapılmış dönüşüm sınıflar bulamadı - ve dize kendimi dönüştürmek için benim girişimleri ve göndermek beyhude görünüyordu.

Any help would be greatly appreciated.

5 Cevap

Mekanizmalar girmeden önce kavramsal olarak onunla başa çıkmak için, ve bu herhangi bir bariz ise özür dilemek, bir dize Unicode karakter dizisi olarak tanımlanabilir, Unicode öldürürsün, her karakter için bir kod noktası olarak bilinen bir kimlik numarasını veren bir veritabanı olma ile çalışmak gerekir. GSM-338 Unicode karakter bir alt kümesini, yani ne yaptığınızı sizin dize codepoints bir dizi ayıklanması ve bu set GSM-338 içerdiği olup olmadığını görmek için kontrol edilir içerir.

// second column of http://unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT
$gsm338_codepoints = array(0x0040, 0x0000, ..., 0x00fc, 0x00e0)
$can_use_gsm338 = true;
foreach(codepoints($mystring) as $codepoint){
    if(!in_array($codepoint, $gsm338_codepoints)){
      $can_use_gsm338 = false;
      break;
    }
}

Yani PHP yerleşik olmayan işlev codepoints tanımını ($ string), bırakır. PHP bir dize yerine Unicode karakter dizisi daha bayt dizisi olarak anlar. Köprü en iyi yolu olarak hızlı bir şekilde yapabilirsiniz UTF8'den içine dizeleri almak ve sürece olabildiğince UTF8'den onları tutmak için - harici sistemlerle uğraşırken diğer kodlamaları kullanmak zorunda, ancak dönüştürmeyi izole edeceğiz bu sisteme arayüzü ve dahili utf8 ile sadece anlaşma.

Sizin codepoints () işlevi var yani utf8 ve codepoints dizileri php dizeleri arasında dönüştürmek için gereken fonksiyonlar, http://hsivonen.iki.fi/php-utf8/ bulunabilir.

Eğer Unicode çizgi-kaçtı karakterleri ("test \ u00f6 \ u00e4 \ u00fc edelim ...") veren harici bir kaynaktan gelen verileri alarak yapıyorsanız, bu dize kaçış biçimi utf8 dönüştürülmesi gerekir. Bunu yapmak için bir fonksiyonun hazırlıksız bilmiyorum biri bulunamazsa eğer, bu dize / regex işleme meselesi + hsivonen.iki.fi fonksiyonların kullanımı, örneğin \ u00f6 vurduğunuzda, değiştirin codepoint 0xf6 bir utf8 temsiliyle.

Bu eski bir konu olmasına rağmen Geçenlerde çok benzer bir sorunu çözmek için vardı ve benim cevap göndermek istedim. PHP kodu biraz basit. Geçerli karakter geçti dizesinin ilk karakterin ASCII değerini döndürür ord($string) function hangi kullanarak bu dizide ise bir dizide GSM geçerli bir karakter kodlarının bir özenle büyük bir dizi ile başlar, daha sonra sadece denetler. Burada bir dize GSM değer olup olmadığını doğrulamak için kullanabilirsiniz koddur.

    $valid_gsm_keycodes = Array(   
        0x0040, 0x0394, 0x0020, 0x0030, 0x00a1, 0x0050, 0x00bf, 0x0070,
        0x00a3, 0x005f, 0x0021, 0x0031, 0x0041, 0x0051, 0x0061, 0x0071,
        0x0024, 0x03a6, 0x0022, 0x0032, 0x0042, 0x0052, 0x0062, 0x0072,
        0x00a5, 0x0393, 0x0023, 0x0033, 0x0043, 0x0053, 0x0063, 0x0073,
        0x00e8, 0x039b, 0x00a4, 0x0034, 0x0035, 0x0044, 0x0054, 0x0064, 0x0074,
        0x00e9, 0x03a9, 0x0025, 0x0045, 0x0045, 0x0055, 0x0065, 0x0075,
        0x00f9, 0x03a0, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, 0x0076,
        0x00ec, 0x03a8, 0x0027, 0x0037, 0x0047, 0x0057, 0x0067, 0x0077, 
        0x00f2, 0x03a3, 0x0028, 0x0038, 0x0048, 0x0058, 0x0068, 0x0078,
        0x00c7, 0x0398, 0x0029, 0x0039, 0x0049, 0x0059, 0x0069, 0x0079,
        0x000a, 0x039e, 0x002a, 0x003a, 0x004a, 0x005a, 0x006a, 0x007a,
        0x00d8, 0x001b, 0x002b, 0x003b, 0x004b, 0x00c4, 0x006b, 0x00e4,
        0x00f8, 0x00c6, 0x002c, 0x003c, 0x004c, 0x00d6, 0x006c, 0x00f6,
        0x000d, 0x00e6, 0x002d, 0x003d, 0x004d, 0x00d1, 0x006d, 0x00f1,
        0x00c5, 0x00df, 0x002e, 0x003e, 0x004e, 0x00dc, 0x006e, 0x00fc,
        0x00e5, 0x00c9, 0x002f, 0x003f, 0x004f, 0x00a7, 0x006f, 0x00e0 );


        for($i = 0; $i < strlen($string); $i++) {
            if(!in_array($string[$i], $valid_gsm_keycodes)) return false;
        }

        return true;

Ben bu kodu php değil biliyorum, ama ben yine de yardımcı olabilir düşünüyorum. Bu ben onun mümkünse (düz metin için benzer bir şey yapabileceğini) GSM 03,38 olarak göndermek için algılamak için yazdığı bir app bunu nasıl. Bu iki çeviri tabloları, Normal GSM biri ve genişletilmiş için birine sahiptir. Ve sonra dönüştürülebilir olmadığını kontrol tüm karakterler aracılığıyla döngüler bir işlev.

#define UCS2_TO_GSM_LOOKUP_TABLE_SIZE    0x100
#define NON_GSM 							 0x80 
#define UCS2_GCL_RANGE                  24
#define UCS2_GREEK_CAPITAL_LETTER_ALPHA 0x0391
#define EXTEND  					          0x001B
// note that the ` character is mapped to ' so that all characters that can be typed on
// a standard north american keyboard can be converted to the GSM default character set
static unsigned char  Ucs2ToGsm[UCS2_TO_GSM_LOOKUP_TABLE_SIZE] =
{           /*+0x0      +0x1        +0x2        +0x3        +0x4        +0x5        +0x6        +0x7*/
/*0x00*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x08*/    NON_GSM,    NON_GSM,    0x0a,       NON_GSM,    NON_GSM,    0x0d,       NON_GSM,    NON_GSM,
/*0x10*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x18*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x20*/    0x20,       0x21,       0x22,       0x23,       0x02,       0x25,       0x26,       0x27,
/*0x28*/    0x28,       0x29,       0x2a,       0x2b,       0x2c,       0x2d,       0x2e,       0x2f,
/*0x30*/    0x30,       0x31,       0x32,       0x33,       0x34,       0x35,       0x36,       0x37,
/*0x38*/    0x38,       0x39,       0x3a,       0x3b,       0x3c,       0x3d,       0x3e,       0x3f,
/*0x40*/    0x00,       0x41,       0x42,       0x43,       0x44,       0x45,       0x46,       0x47,
/*0x48*/    0x48,       0x49,       0x4a,       0x4b,       0x4c,       0x4d,       0x4e,       0x4f,
/*0x50*/    0x50,       0x51,       0x52,       0x53,       0x54,       0x55,       0x56,       0x57,
/*0x58*/    0x58,       0x59,       0x5a,       EXTEND,     EXTEND,	    EXTEND,   	EXTEND,		0x11,
/*0x60*/    0x27,   	0x61,       0x62,       0x63,       0x64,       0x65,       0x66,       0x67,
/*0x68*/    0x68,       0x69,       0x6a,       0x6b,       0x6c,       0x6d,       0x6e,       0x6f,
/*0x70*/    0x70,       0x71,       0x72,       0x73,       0x74,       0x75,       0x76,       0x77,
/*0x78*/    0x78,       0x79,       0x7a,       EXTEND, 	EXTEND,		EXTEND,		EXTEND,		NON_GSM,
/*0x80*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x88*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x90*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0x98*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0xa0*/    NON_GSM,    0x40,       NON_GSM,    0x01,       0x24,       0x03,       NON_GSM,    0x5f,
/*0xa8*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0xb0*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,
/*0xb8*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x60,
/*0xc0*/    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x5b,       0x0e,       0x1c,       0x09,
/*0xc8*/    NON_GSM,    0x1f,       NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x60,
/*0xd0*/    NON_GSM,    0x5d,       NON_GSM,    NON_GSM,    NON_GSM,    NON_GSM,    0x5c,       NON_GSM,
/*0xd8*/    0x0b,       NON_GSM,    NON_GSM,    NON_GSM,    0x5e,       NON_GSM,    NON_GSM,    0x1e,
/*0xe0*/    0x7f,       NON_GSM,    NON_GSM,    NON_GSM,    0x7b,       0x0f,       0x1d,       NON_GSM,
/*0xe8*/    0x04,       0x05,       NON_GSM,    NON_GSM,    0x07,       NON_GSM,    NON_GSM,    NON_GSM,
/*0xf0*/    NON_GSM,    0x7d,       0x08,       NON_GSM,    NON_GSM,    NON_GSM,    0x7c,       NON_GSM,
/*0xf8*/    0x0c,       0x06,       NON_GSM,    NON_GSM,    0x7e,       NON_GSM,    NON_GSM,    NON_GSM
};

static unsigned char Ucs2GclToGsm[UCS2_GCL_RANGE + 1] =
{
/*0x0391*/  0x41, // Alpha A
/*0x0392*/  0x42, // Beta B
/*0x0393*/  0x13, // Gamma
/*0x0394*/  0x10, // Delta
/*0x0395*/  0x45, // Epsilon E
/*0x0396*/  0x5A, // Zeta Z
/*0x0397*/  0x48, // Eta H
/*0x0398*/  0x19, // Theta
/*0x0399*/  0x49, // Iota I
/*0x039a*/  0x4B, // Kappa K
/*0x039b*/  0x14, // Lambda
/*0x039c*/  0x4D, // Mu M
/*0x039d*/  0x4E, // Nu N
/*0x039e*/  0x1A, // Xi
/*0x039f*/  0x4F, // Omicron O
/*0x03a0*/  0X16, // Pi
/*0x03a1*/  0x50, // Rho P
/*0x03a2*/  NON_GSM,
/*0x03a3*/  0x18, // Sigma
/*0x03a4*/  0x54, // Tau T
/*0x03a5*/  0x59, // Upsilon Y
/*0x03a6*/  0x12, // Phi 
/*0x03a7*/  0x58, // Chi X
/*0x03a8*/  0x17, // Psi
/*0x03a9*/  0x15  // Omega
};

bool Gsm0338Encoding::IsNotGSM( wchar_t szUnicodeChar )
{
    bool	result = true;
    if( szUnicodeChar < UCS2_TO_GSM_LOOKUP_TABLE_SIZE )
    {
    	result = ( Ucs2ToGsm[szUnicodeChar] == NON_GSM );
    }
    else if( (szUnicodeChar >= UCS2_GREEK_CAPITAL_LETTER_ALPHA) &&
    			(szUnicodeChar <= (UCS2_GREEK_CAPITAL_LETTER_ALPHA + UCS2_GCL_RANGE)) )
    {
    	result = ( Ucs2GclToGsm[szUnicodeChar - UCS2_GREEK_CAPITAL_LETTER_ALPHA] == NON_GSM );
    }
    else if( szUnicodeChar == 0x20AC ) // €
    {
    	result = false;
    }
    return result;
}

bool Gsm0338Encoding::IsGSM( const std::wstring& str )
{
    bool	result = true;
    if( std::find_if( str.begin(), str.end(), IsNotGSM ) != str.end() )
    {
    	result = false;
    }
    return result;
}

PHP6 iyi unicode desteğine sahip olacak ama kullanabileceğiniz birkaç fonksiyonlar vardır.

Benim ilk düşünce oldu mb_convert_encoding but as you said this will shorten messages to 70 chars - so perhaps you can use this in conjunction with mb_detect_encoding ?

Bkz: Multibyte Functions

preg_match('/^[\x0A\x0C\x0D\x20-\x5F\x61-\x7E\xA0\xA1\xA3-\xA5\xA7'.
    '\xBF\xC4-\xC6\xC9\xD1\xD6\xD8\xDC\xDF\xE0\xE4-\xE9\xEC\xF1'.
    '\xF2\xF6\xF8\xF9\xFC'.
    json_decode('"\u0393\u0394\u0398\u039B\u039E\u03A0\u03A3\u03A6\u03A8\u03A9\u20AC"').
    ']*$/u', $text)

veya

preg_match('/^[\x0A\x0C\x0D\x20-\x5F\x61-\x7E\xA0\xA1\xA3-\xA5\xA7\xBF\xC4-\xC6\xC9\xD1\xD6\xD8\xDC\xDF\xE0\xE4-\xE9\xEC\xF1\xF2\xF6\xF8\xF9\xFCΓΔΘΛΞΠΣΦΨΩ€]*$/u', $text)