Title

VisualStudio2013でビルドするとWindowsXP/2003Serverで起動できない

VisualStudio2013では、デフォルトの設定でWindowsXPが切り捨てられています。

フレームワークのバージョンとかでなく、素のWindowsAPIのみを利用していても起動できません。
さすがにもうWindowsXPはサポートしなくても良いのかもしれませんが、Windows2003ServerはWindowsXPと同じ扱いですので、WindowsXPで起動できないとWindows2003Serverでも起動できません。
(Windows 2003Serverは15年7月くらいまでサポート期間があります・・・)

以下の設定を変更すると起動できるようになります。

140321vs2013

もはや動作確認環境もなく、なかなか気づきにくいので気をつけないといけませんね。

・・・しかしVisualStudio高いよねーー。。
自分の作るWindowsアプリケーションは本当に素のC++で書いているので別にどんなコンパイラでもコンパイルできるんですよね。だから高く感じますが・・・
しかし、VisualStudio2013のエディタはかなり良くなりました。エディタとして買ってます。

iOSでSMBライブラリを実装する(その6)

そろそろメモとして書くことがなくなってきました。
一応リリースできましたしね。
SMBは「シンプルの逆」のものなので、完全な互換性を目指すとかなり茨の道を行くことになります。

最後に、ものすごく参考になりそうな本をみつけたのでご紹介。

Implementing CIFS: The Common Internet File System

cifsimp

タイトルまんまですね。
最初に存在を知っていれば・・・ということはよくあります。
ここに辿り着いただけでも褒めてください。

さて、実用としては色々考えるところもありますが、やっぱりSambaのスケールの大きさとか、市販のCIFSライブラリが長年開発されて売られ続けていることとか、使いやすいライセンスの優れたOSSがみつからないとか、ようするにSMBは複雑ってことですね。

SMB初期実装をリリース

さて、せっかく作ったのでComicGlassのSMB対応バージョンをリリースしました。

予想はしていましたが、いくつか互換性で問題が発生しています。
Windows,Samba,MacはチェックしていたのでOKだったのですが、Sambaのバージョンが古いもの、もしくは設定がちょっと古風になっているもの、あとWindowsでもSambaでもMacでもないもので問題がおきました。

一つ目は、パスワードが設定されていないNAS(WindowsはOK)に接続したとき、ストリーミングすると落ちます。
これはプロトコルの解釈というよりは、単純に値の受け渡しミスでした。
内部的にユーザー名とドメインをつなげて指定できるようにしていたのですが、空だとnilになって文字列のパースで落ちます。
こちらは1行修正するだけなので、すぐに修正版出せる予定です。

2つ目はAirMac Time Capsuleです。
こちらも想定どおりといえば想定どおりなのですが、認証方式の問題で接続がうまくいきません。

具体的にはAirMac Time Capsuleでは「Extended Security Negotiation」フラグがオフになっています。

airmac

手元で事前に試した限り、Extended Security Negotiationを使わないデバイスはなかったので、省力化のために実装を省きました。
しかし身近なところにありました。

Extended Security Negotiationがオフの場合でも認証なしの場合のみ対応していたのですが、AirMac Time Capsuleは認証も要求するのでダメです。はい。

他にも、なにかと互換性の問題が起きる可能性は否定できず(なにせSMBはとても歴史あって方言の多いプロトコルなので・・・)、根本的な対策ができたらなと思ってるところです。
(決まりましたらお知らせします)

AirMac Time Capsuleの対応についてはしばらくお時間ください。

iOSでSMBライブラリを実装する(その4)~あると便利なもの

今回はただの愚痴ですが・・・。

SMB/CIFSの仕様をみると、データの途中にいきなり可変長データが入っていたりします。
さらにpaddingがいたるところに出てきます。

また、変数は存在するものの、実際のところどういう値にしていいのか、定数としてどんなものがあるのかわからないことが多々あります。

そんなときはプロトコルアナライザです。
WindowsServer系ならばリソースキットで利用できますが、WireSharkなんかも便利です。

そして、絶対あったほうが良いもの・・。

それはポートミラーリング、またはポートモニタリング機能がついたスイッチングハブです。
完全なリピータハブがあればそれでもいいですが、おそらく10BASE-Tの時代のものしか無いと思うので・・・。

数年前までは何万円もしましたが、今では1万円を切る商品もあるみたいです。

iOS向けSMBライブラリを実装する(その3)~NetBIOS名の解決

Windowsで使われる、NetBIOSまわりを頑張ってみます。

やりたいことは、Windowsコンピュータ名(NETBIOS名)からIPアドレスを取得することです。

NetBIOSはとにかく不可解です。
本当に不可解なんですが、歴史的背景があるので仕方がありません。
どのくらい古いかというと1980年代くらいなので仕様書もイマイチ読みづらく、後の改変も多数あるので本当にわかりづりです。

まずNetBIOSはTCP/IPとは別物です。
現在ではプロトコル部分をNetBEUI、インターフェイス部分をNetBIOSと呼ぶようですが、元はインターフェイス(API)からプロトコルまですべてひっくるめた規格でした。

NetBEUIは現在では使われることは無くなりましたが、NetBIOSのインターフェイスだけは利用され続けているというわけです。
NetBIOSをTCP/IPで利用できるようにしたものがNetBIOS over TCP/IPです。(TCP/IPとか言いながらUDP/IPも多用します)
これ時代もWindows3.x時代のものなので何かと理解しづらいです。

さて、関係ありそうな、NetBIOS over TCP (NBT) Extensions NetBIOS over TCP (NBT) Extensions[MS-NBTE]をまず見てみると
名前解決についてはRFC1002を見るように書いてあります。

RFC1002の内容は「NetBIOS-over-TCP」となっています。
日付は March 1987・・・。
読んでみると・・・なんか意味不明・・ですががんばって読む。

とりあえずパケットのフォーマットはこう

                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         NAME_TRN_ID           | OPCODE  |   NM_FLAGS  | RCODE |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          QDCOUNT              |           ANCOUNT             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          NSCOUNT              |           ARCOUNT             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

で、名前解決のリクエストはこういう固定値を入れる

4.2.12.  NAME QUERY REQUEST

                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         NAME_TRN_ID           |0|  0x0  |0|0|1|0|0 0|B|  0x0  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          0x0001               |           0x0000              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          0x0000               |           0x0000              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   /                         QUESTION_NAME                         /
   /                                                               /
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           NB (0x0020)         |        IN (0x0001)            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Bはブロードキャストフラグなので、1で固定みたいです。
なのでフラグ部分は0x0110。

QUESTION_NAMEの部分はRFC 883を使ってコード化しろって書いてます! 
これがまだ何故??というやり方で頭に???浮かびっぱなしです。

とりあえずNETBIOS名は15文字です。本来は16文字でしたが、最後の1バイトを別の用途に割り当てたため15文字。
15文字に満たない場合はスペース(0x20)で埋めます。

16文字目はサフィックスで種別を表すのですが、
0x00だとワークステーション サービス
0x20だとファイル サーバー サービス
0x1bだとドメイン マスタ ブラウザ
・・・などなどを表すようですが、、
これはもともとのLAN Managerの仕様ではなくMicrosoftの拡張仕様です。
どうやら0x00はクライアント、0x20がサーバサービスを示すようなのでここでは0x20が正解だと思われます。(実際にはどちらも名前登録されていて、反応もしてくれるので良いのですが)

で、肝心のNETBIOS名の格納方法です。
最初の1バイトは0x20を指定します。0x20=長さが32byteの意味で、NETBIOS名の場合は32byte固定と書いてあるので必ず0x20を指定。

NEBIOS名+サフィックスの16byteを以下の手順で符号化して32Byteにします。
最後にNULL(0x00)くっつけるので、長さを表す先頭の0x20と合わせて34byteになります。
これがQUESTION_NAMEになります。

NETBIOS名の符号化は、
まず文字コードを4バイト単位にわけます。
空白文字(0x20)であれば0x2と0x0です。
0x0をA、0x1をB、0x2をC・・・という感じで文字を割り当てます。
0x20であれば「CA」になります。

つまりNETBIOS名が「FRED」であれば「EGFCEFEECACACACACACACACACACACACA」になります。

さて、これをUDPでブロードキャストすれば該当ホストがレスポンスを返してくれます。
iOSで1024番以下のポートをbindできるのか?とちょっと不安でしたが、やってみたら大丈夫でした。

レスポンスの内容は以下のとおり

4.2.13.  POSITIVE NAME QUERY RESPONSE

                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         NAME_TRN_ID           |1|  0x0  |1|T|1|?|0 0|0|  0x0  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          0x0000               |           0x0001              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          0x0000               |           0x0000              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   /                            RR_NAME                            /
   /                                                               /
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           NB (0x0020)         |         IN (0x0001)           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                              TTL                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           RDLENGTH            |                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
   |                                                               |
   /                       ADDR_ENTRY ARRAY                        /
   /                                                               /
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

TTLより前はリクエストと同じ。
ADDR_ENTRY ARRAYにIPアドレスが入ります。
(複数ある場合は複数入ります。パケットの送信アドレスを見るか、自分のネットワークマスクと較べてどれを利用するか決めます)

実際には名前の解放パケットとかも飛んでくるようですが(それを見てキャッシュから削除する)、iOSでそれを監視し続けるのは非現実的なので無視します。

なお、IPv6の場合はLLMNR(Link-Local Multicast Name Resolution)を使う必要があります。
今回はIPv4だけでいいのでそっちはやりません。
(そのくらいの知識がある人はIPアドレスでわかるでしょうし・・・)

さて、これでコンピュータ名(NETBIOS名)を解決できるようになりました。
まぁ、なったところでどう使うかは悩ましいところなんですけどね。

iOSでSMBライブラリを実装してみる(その2)~NTLM認証

Windows関連情報は運用を目的にしたものが多く、コーディング例はあんまり聞かないのでメモ的に書いておきます。

SMBの認証にはLM認証、NTLMv1認証、NTLMv2認証、Kerberos認証のいずれかを使います。
Kerberos認証は鍵交換でActiveDirectly環境想定のものなので除外。

LM認証はNTLMv1認証はだいぶ古いにもかかわらずつい最近まで使われていましたがWindows7からはデフォルト無効になっているようなのでこちらも使わない方針で行きます。
ようするに面倒なのでNTLMv2だけ対応します。
あと、まず非対応ということはあり得ないので、Unicodeだけ対応します。

さて、NTLMは「NT LAN Manager Authentication Protocol」のことらしいです。
Microsoftの仕様書名は[MS-NLMP]です。

基本的には認証情報をバイト列に並べているだけなので仕様書を読みながら実装すればなんとか出来ます。
SMB/CIFSがアライメントやら謎のpaddingやらとても実装しにくいのに比べると可変長データをpayloadにまとめているので少しだけ気楽です。

クライアント側で生成する必要があるのは、NEGOTIATE_MESSAGEとAUTHENTICATE_MESSAGEです。
前者は本当に必要な情報を連結してバイト列にしているだけなので楽勝。それでも実際実装してみると一発ではなかなか思い通りにならないのですが・・・。

後者のAUTHENTICATE_MESSAGEもほとんど同じですが、NEGOTIATE_MESSAGEに対してサーバから返されたCHALLENGE_MESSAGEに含まれる情報を使ってチャレンジレスポンスを計算する必要があります。
それがNTLMv2なわけですね。
AUTHENTICATE_MESSAGEのうち、計算が必要なのはNTLMv2 Responseというフィールドです。

といっても、使うのはmd4とmd5だけなんですね。
試行錯誤の結果正しい結果を出せるようになったのでメモ。

入力
・ドメイン(大文字のみ,UTF16LittileEndian)
・ユーザ名(大文字のみ,UTF16LittileEndian)
・パスワード(UTF16LittileEndian)
※ドメインとユーザー名は全て大文字に変換しておく
※文字列のNULLターミネーションは不要(含めない)

サーバから(CHALLENGE_MESSAGEの内容)
・Server challenge (8byte)
・TargetInfo (可変長)

(クライアント側で)生成するもの
・タイムスタンプ(8byte)
・Client challenge (8byte乱数)

1.パスワードのmd4ハッシュを求める
2.ユーザ名とドメイン名を連結する(例:「user」+[Domain]→「USERDOMAIN」 )
※ここを先入観でDOMAIN+USERの順番だと思い込んでハマりました・・・
3.2に対して、1を鍵として、hmac_md5を計算する
4.以下を連結する(これをblobと言うらしい)
  署名(固定値=0x01010000)
  4byteの予約領域その1(0x00000000)
  タイムスタンプ(8byte)
  Client challenge(8byte)
  4byteの予約領域その2(0x00000000)
  TargetInfo
  4byteの予約領域その3(0x00000000)
5.Server challengeと4を連結する
6.5に対して、3を鍵として、hmac_md5を計算する
7.6と4を連結する

7で出来たものがNTLMv2レスポンスになります。
ややこしいですね。

MD4はRFC 1320
MD5はRFC 1321
HMACは RFC 2104に規定されています。
なお、それぞれC言語コードが附属しています。
たいして計算量も無いので最適化も不要でしょうから、そのまま使ってもOKかと思います。ただしライセンス表記が必要です。
探せばそのあたりをクリアしたコードも見つかります。
(僕はmd4はそのまま使いました。md5は以前準備したコードがあったのでそっちを利用)

基本的に、SMBと同じく全てリトルエンディアンが使われます。
普通ネットワークバイトオーダーと言えばビッグエンディアンなんですけどね。
最初はエンディアン気にしてコード書いてましたが、どうせiPhoneもリトルエンディアンだし途中から面倒になってリトルエンディアン環境想定で作りました。

さて、これでSMBサーバと認証ができるようになりました。

次回はWindowsファイル共有に使うNETBIOS名(ホスト名)をNetBIOS over TCP/IPを使って名前解決(IPアドレスを取得する)をやってみたいと思います。
まぁ、IPアドレスでアクセスすれば良いので不要な気もしますが。。

欲を言えばBROWSERプロトコルを使ってネットワーク上のNETBIOSホスト名を自動収集したいところですが、、まぁNASとかはBonjourに対応してるから不要な気もします。

2015-05-18 修正 challengeのスペルが違うというお恥ずかしいミスがありましたのでこっそり修正。

夜更かししないためのライフハック

昔実践していたことがあるのが、ひとりサマータイムもどき。
自分だけ時計を1時間か2時間ずらして生活します。(時計を進めます)

そうすると時計が午前2時とか3時とかになるまで起きていても平気です。(気分ですよ気分)
実際には午前0時頃なわけですが、さすがに(表示が)1時、2時になると寝ようかなーという気分になるわけです。

これはこれでよいのですが、昼間は他の人と時間がずれていて何かと不便です。

といわけで、帳尻合わせて夜だけ時計を進める歪みタイムゾーンを考えてみました。

・午前6時から午後6時までは普通の時計と同じです。
・午後6時からちょっと加速して、午後10時になるころに表示は24時(0時)になります。
・午後10時から午前2時までは表示は2時間進んだまま、通常と同じ速度で表示が進みます。
・午前2時から午前6時の間に2時間の進みを帳尻合わせします。

<図解>

とりあえずみんな笑顔でハッピーということで「スマイルタイム」と名づけました。
(というかいろいろ検索したんだけどわかりやすくて取れるドメインがこれでした)

http://smiletime.info/ <スマイルタイム>

↑思いついたらすぐになんかしてみたくなるので、説明のためのサイト作りました。全てパブリックドメイン的に扱って構わないので是非お試しください。普及活動します(弱々しく)
 寝る時間だけではなく、仕事もはやく終えるようになったらいいですよね。
 iPhone時計アプリとかもそのうち作ってみる。

iOS上でSMB/CIFS(Windowsファイル共有)をゼロから実装してみる

何故か全くライブラリが見つからないSMB/CIFS。
ググってみても、「SMBのiOSライブラリないの?(そもそもObj-cに限定しなくても無い)」「sambaがGPL、ぐぬぬぬ・・・」という記事しか見当たらない。組込み向けの製品はいくつか見つかりましたが、たぶん個人で買えるようなものじゃない。
きっと実装は厄介なんだろうなと見る気もしてなかったですが、風邪でダウンしていたので、その時に一度気合を入れてテストしてみました。

なお、tangoというOSSがあるようですが、うまく動かない。
恐らく認証関連が古いせいで最近のWindowsでは動かないぽい。
extended security flagが立っていると即座にエラー返すようなのできっとダメだろう、ってことでtangoは諦める。

SMBはSMB1とSMB2があって、SMB2は大きなバッファが扱えて高速LANで効率がいいようですが、NASとかで対応していないものもあるかもしれないし、iPhoneのWifiからではほとんど速度は変わらない(と思う)のでまずSMB1にトライ。(SMB1の仕様書読んでいるうちに、ファイルオフセット指定が32bitしかなく、2G超えるファイルダメじゃん!って気づいたけど気づかなかったことにします:→追記で訂正)

悪名高いMicrosoftの仕様書を読み解くわけですが、SMBは魑魅魍魎な方言やら実はこうでしたー! 残念! みたいな実装があって苦しむと噂には聞いております。

さて、さて、
仕様書読むと案外単純な通信です。
これはいける。

流れは、
・ネゴシエーション
・セッションリクエスト(認証)
・ツリー接続、一覧取得、(ここでパイプ、RPCの仕様書を読まされる(涙))
・ファイル一覧の取得 (ワイルドカード*でFindFileする。ルートディレクトリだと失敗するのでちょっと変える必要ある
・データの転送(実は簡単な命令っぽい)

という感じで、バイナリデータなのでC言語では扱いやすい(はず・・)

しかしセッションリクエストで早速ハマる。

[MS-CIFS]306ページ、2.2.4.53 SMB_COM_SESSION_SETUP_ANDX (0x73)

This command was introduced in the LAN Manager 1.0 dialect.
The formats of the request and response messages have changed since the command was first defined. The CIFS format, as defined for the NT LAN Manager dialect, is presented here. This format MUST be used when the NT LAN Manager dialect has been negotiated.
(後略)

このコマンドはLAN Manager1.0のときの(方言で?)定義された。
このコマンドが最初に定義されてから、リクエストと応答メッセージのフォーマットが変わったよ。

うーん。LAN Manager1.0はIBMの頃の仕様でもう使われていないので、NT LMを使うみたいね。
Wordデータは26 bytesなので、WordCoundは13になるはず??? よくわからん

他の通信をパケットキャプチャしてみるとWordCountが12=24Byteしかない。1バイトどこいったー?

試しにきにせず26Byteで送ってみたら見事エラーでございます・・・。

と思ったら別のファイルの[MS-SMB]の方の53ページにextended security flagを使う時にはSecurityBlobLengthを使えって書いてあった。・・・といった具合に仕様書読むにもコツが必要な模様。

とりあえずWindows7とNAS相手にツリー一覧取得までは出来たので、頑張ればなんとかなるかなー。
どうも一番面倒なのはツリー一覧取得するところだったっぽい。
もう少しちゃんとエラー処理とか、ネゴシエーションやらないと実用的には使えないと思うので作業量は多そうですが。

時間かかる要素その2は、SMB通信に使うNTLMの暗号化をどうするか。
とりあえず外部ライブラリ使って認証が通ることは確認しましたが、ここも自前で実装するとなると読まなければならない仕様書がまた増えて面倒くさい。
まぁ、こちらの方が内容はある程度クリアなので実装することは出来そうですが、まっとうにやったら時間かかりそうです。まっとうじゃない方法探します。

NTLMもUIWebViewでは使えるので、API公開してくれたらいいのに・・・。

ComicGlassへはうまく出来たら実装します。

追記:

だいぶ分かってきました。
上記記述にいくつか間違いがあったので一応訂正。

ファイルのリードについては見ていた資料が古かったようで、新しい資料にはOffsetの上位バイトのフィールドがありました。
(SMB_COM_READ_ANDX==0xeE最後の4バイト,Optinal)
よって2GBを超えるファイルもオフセット付で扱えます。
またTimeoutがTimeout_or_MaxCountHighになっており、ファイルを読む場合はMaxCountHighとして扱うように変わってました。
ネゴシエーションの時に対応非対応を設定できるようです。
(しかしWindowsXPの通信見てみると使ってない・・・)

ときおり出てくるDataOffsetとかの意味がわかって受信データのpaddingサイズ不要が要らないことがわかりました。(DataOffsetでデータの先頭がわかる)

フィリピン災害への寄付

【寄付ハック】フィリピン災害へ寄付した人に、オレが自腹でiPad miniプレゼントキャンペーン(fladdictさん)

fladdictさんはいつもアイデア素晴らしい。
全員が得するやり方でないと支持されにくいんですよね。うまい。
まんまと宣伝しちゃうぜ!

僕も応募したよー

Objective-Cで中国語文字コードのC文字列をNSStringに読み込む

これわからずに非常に苦労しました。
そもそも中国語の文字コードなんて知らんし・・・。

NSStringEncodingの一覧には中国語っぽいものが無いんですよね。
下のように日本語は優遇されている気がしますが、その他言語はどうするんだろうって思いますよね。

enum {
    NSASCIIStringEncoding = 1,		/* 0..127 only */
    NSNEXTSTEPStringEncoding = 2,
    NSJapaneseEUCStringEncoding = 3,
    NSUTF8StringEncoding = 4,
    NSISOLatin1StringEncoding = 5,
    NSSymbolStringEncoding = 6,
    NSNonLossyASCIIStringEncoding = 7,
    NSShiftJISStringEncoding = 8,          /* kCFStringEncodingDOSJapanese */
    NSISOLatin2StringEncoding = 9,
    NSUnicodeStringEncoding = 10,
    NSWindowsCP1251StringEncoding = 11,    /* Cyrillic; same as AdobeStandardCyrillic */
    NSWindowsCP1252StringEncoding = 12,    /* WinLatin1 */
    NSWindowsCP1253StringEncoding = 13,    /* Greek */
    NSWindowsCP1254StringEncoding = 14,    /* Turkish */
    NSWindowsCP1250StringEncoding = 15,    /* WinLatin2 */
    NSISO2022JPStringEncoding = 21,        /* ISO 2022 Japanese encoding for e-mail */
    NSMacOSRomanStringEncoding = 30,

    NSUTF16StringEncoding = NSUnicodeStringEncoding,      /* An alias for NSUnicodeStringEncoding */

    NSUTF16BigEndianStringEncoding = 0x90000100,          /* NSUTF16StringEncoding encoding with explicit endianness specified */
    NSUTF16LittleEndianStringEncoding = 0x94000100,       /* NSUTF16StringEncoding encoding with explicit endianness specified */

    NSUTF32StringEncoding = 0x8c000100,                   
    NSUTF32BigEndianStringEncoding = 0x98000100,          /* NSUTF32StringEncoding encoding with explicit endianness specified */
    NSUTF32LittleEndianStringEncoding = 0x9c000100        /* NSUTF32StringEncoding encoding with explicit endianness specified */
};
typedef NSUInteger NSStringEncoding;

もちろんUTF8ならいいのですが、Windowsで作ったテキストファイルなどはUnicodeになっていないことが多いようです。
日本語でもShiftJISが未だに使われますよね。

日本人でこの問題に言及している方がいなかったので情報共有で書いておきます。

結論を書きますと、CFStringConvertEncodingToNSStringEncodingを使えばその他の文字コードも読み取りできるようです。
中国語(簡体)ではGB 18030というコードが使われるようなので、以下のような感じになります。

NSStringEncoding encode = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
str = [NSString stringWithCString:cstring encoding: encode];

さて、知っている方いらっしゃったら教えてほしいのですが、台湾で使われるトラディッショナル(繁体?)な方のコードと、韓国語はどのようなコードが使われているのでしょうか?
台湾と韓国のユーザーの方もそれなりにいらっしゃるので対応したいのですがそもそもサンプルも無ければハングルを入力する術もないので・・・。

ちなみに、自動判別は無理だと思われます。。

追記:
とりあえずEUC-krが一般的っぽいので、それに対応しておいてみます。
そういうファイルが無いので確認はできませんが・・・。
台湾(?)ではbig5が普通と聞きましたので、それに対応しておいてみます。

ラテン文字はどう区別していいのかわかんないですね。
とりあえず手動で全て選択できるようにしておきます。力技。

カレンダー

2024年3月
 123
45678910
11121314151617
18192021222324
25262728293031

▲Pagetop