Menu

#71 '\0'を含むクリップボードテキストを貼り付け

closed
nobody
None
5
2012-11-09
2006-12-18
maru
No

data:5686の件

再現を取ってみるとクリップボードの中身は
0xA0 0x00 0x0D 0x0Aという行末になっていた。
結果としてCMemory::SetDataSzで0x00で切られる。

単に貼り付けるだけなら…。
細かいことはこれから考えるとして
とりあえずは、途中経過。

Discussion

  • maru

    maru - 2006-12-18

    検討中

     
  • maru

    maru - 2006-12-24

    Logged In: YES
    user_id=1480232
    Originator: YES

    [5686] ペーストが途中で切れるようです。 返信 削除
    ▽ 2006/12/16 (土) 11:53:39 1ユーザ
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1)
    サクラエディタをメインで使っている1ユーザです。

    ある日、もらったExcelファイルのある1列をコピーしサクラエディタにペーストすると、全部コピーできずに、途中で切れてしまいました。
    Windowsのメモ帳、秀丸エディタでも同様にためしたのですが、途切れませんでした。
    途切れた部分には何か変なコードがはいってたようで、バイナリエディタで見てみると、文字列の後にA0というコードが入ってました。
    どうやってコードを入れたのか分かりませんが、サクラエディタでもメモ帳と同様にペーストできて欲しいですが、無理でしょうか?

    ※最新版の1.5.13.1でもだめなようでした。

    変なコードが入っている時、メモ帳、秀丸エディタともに、保存する際に
    コードを「?」に変更するけどもいいかというようなダイアログが出ました。

    --------------------------------------------------------------------------------

    [5689] Re:ペーストが途中で切れるようです。 返信 削除
    ▽ 2006/12/16 (土) 17:14:27 maru
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

    Excelファイルのある1列をコピーしサクラエディタにペーストすると、全部コピーできずに、
    再現しません。A0の入ったデータはExcel、サクラエディタ、メモ帳
    相互に問題なくペーストでき、保存もできました。
    0AではなくてA0なんですよね?

    --------------------------------------------------------------------------------

    [5691] Re2:ペーストが途中で切れるようです。 返信 削除
    ▽ 2006/12/16 (土) 23:21:16 1ユーザ
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1)
    ▼ maruさん

    Excelファイルのある1列をコピーしサクラエディタにペーストすると、全部コピーできずに、
    再現しません。A0の入ったデータはExcel、サクラエディタ、メモ帳
    相互に問題なくペーストでき、保存もできました。
    0AではなくてA0なんですよね?

    はい。バイナリエディタで見たらコードのA0です。
    (文字列の「A」と「0」ではないです。勘違いをさせてしまっていたらすみません。)
    具体的には、
    Excelでみた時例えば、

    XXX.XXX.XXX.XXX
    YYY.YYY.YYY.YYY_
    ZZZ.ZZZ.ZZZ.ZZZ

    見たいな感じでデータがあって、「_」の部分がExcel上ではスペースっぽく表示されます。
    ペーストすると、
    XXX.XXX.XXX.XXX
    YYY.YYY.YYY.YYY
    で途切れます。
    バイナリエディタで見ると
    YYYの次の部分がA0が着て次に0Bとなってました。
    周辺のデータを見るとデータの次には大抵0Bが入っているので、「0B」がセルの終わりの意味になっているのかと思います。
    それで、A0が入っているという判断しました。

    改めて検証のため、新規にExcelファイルを作成して、上記3行をA列にコピーし、保存。
    バイナリエディタで「YYY_」の部分を探して「_」の部分をコード「A0」に変更し保存。
    Excelで開いて、A列をコピー、サクラエディタでペーストしたら、再現しました。
    もらったExcelファイルでどうやってコードのA0が入ったか分かりませんが、一応再現しましたが、私の環境だけでしょうか?
    WindowsXP SP2
    Excel2003
    です。

    --------------------------------------------------------------------------------

    [5697] Re3:ペーストが途中で切れるようです。 返信 削除
    ▽ 2006/12/18 (月) 03:01:17 じゅうじ
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
    ▼ 1ユーザさん
    エクセルですが、名前を付けて保存の所で、ファイルの種類を選ぶと、テキストになり編集できますよ。
    テキスト(タブ区切り)(*.txt)
    CSV(カンマ区切り)(*.csv)

    私としましてはあまり、お役に立てなくて。よろしいですか。

    --------------------------------------------------------------------------------

    [5702] Re4:ペーストが途中で切れるようです。 返信 削除
    ▽ 2006/12/19 (火) 14:55:41 じゅうじ
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1)

    dev:3946
    dev:4244 みくさん提案 クリップボード形式を指定して貼り付け
    data:4244 の間違いですね、3度も出てくるので、行けず。

    --------------------------------------------------------------------------------

    [5693] Re:ペーストが途中で切れるようです。 返信 削除
    ▽ 2006/12/17 (日) 11:27:17 じゅうじ
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
    ▼ 1ユーザさん

    どうやってコードを入れたのか分かりませんが、サクラエディタでもメモ帳と同様にペーストできて欲しいですが、無理でしょうか?

    無理だと思います、ヒントはクリップボードにも種類が有って、コピーするだけで様々な形式で、クリップボードに保存され、
    その中の1つの形式から、ペーストしてくるように、Windowsが作られている為です。過去ログ御覧になればそのあたりの詳しい話が載ってます。

    一度、Windowsのメモ帳に貼り付けて、ファイルを保存し、
    それから、そのファイルをSAKURAで開くのでは、どうですか?

    --------------------------------------------------------------------------------

    [5694] Re2:ペーストが途中で切れるようです。 返信 削除
    ▽ 2006/12/17 (日) 21:14:36 1ユーザ
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1)
    ▼ じゅうじさん

    一度、Windowsのメモ帳に貼り付けて、ファイルを保存し、
    それから、そのファイルをSAKURAで開くのでは、どうですか?

    始から途切れると分かっていればいいのですが、メインのエディタをサクラエディタとしているため、途中に変なコードが入って途切れに気づかずに処理してしまうことになります。
    後からおかしいと指摘されて気づいたのですが、会社でサクラエディタを推奨していましたが、メモ帳と秀丸エディタで出来ることがサクラエディタで出来ないとなると、ちょっとそこをつつかれて秀丸エディタを買ってくれという声が出てきそうで...
    また、一度作ったExcelファイルを送り元(海外から送られてくる)がなかなか直さなかったりするため、更新されてまた送ってきた時に、また同じことが起きると思うとメモ帳のようになって欲しいなと思った次第です。
    ※これがたまに送られてくるファイルなので、変なコードが入ってることを忘れてしまうんです。

    --------------------------------------------------------------------------------

    [5701] Re3:ペーストが途中で切れるようです。 修正 返信 削除
    ▽ 2006/12/19 (火) 02:26:38 maru
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
    関連は>>dev:3965のあたりみたいです。
    ちょっと調べてみます。続きは#1618265

     
  • maru

    maru - 2006-12-24

    Logged In: YES
    user_id=1480232
    Originator: YES

    詳しくはhttp://sakura.qp.land.to/?Develop%2F5に書きましたが
    今回の問題は '\0' をコピーペーストできるようにするだけでは
    解決しない部分のようです。

    簡単に言うと、CMemory::MemUnicodeToSJISのあたりをどのような変換仕様
    にしたら良いか、という話になります。

    現状で、クリップボードにU+00A0が入っているとして
    CF_UNICODETEXTを取得 > CMemory::MemUnicodeToSJISでSJISに変換 > CMemory::MemSJISToUnicodeで元に戻す
    の順で実行すると、値は次のように変化します。
    U+00A0 > 0xA0 0x00 > U+0A00 U+0000

    問題点
    ・0xA0自体はサクラエディタで問題なく扱えるデータなのに、Unicode(U+00A0)との相互変換ができない
    ・CF_TEXTを利用するアプリケーションと動作が異なる
    ・CF_UNICODETEXTを優先する動作はdev:3934のあたりの都合によるため、変更はむずかしい
    ・wctombも意外と微妙
    ・CMemory::MemSJISToUnicodeでmbtowcが変換に失敗したときの救済処理がビッグエンディアンを出力している
    ・CEditView::MyGetClipboardDataからCMemory::MemUnicodeToSJISを呼び出すのもあまり美しくない。(CMemory::UnicodeToSJISを経由すべきだろうから)
    ・GlobalSize()によるサイズをクリップボードのテキストサイズとして問題ないか
    などです。

    全部を解決するのは仕様上困難と思われ、対応可能な範囲内で妥当な内容のみ修正したいと思います。
    ところで、テキストデータでクリップボードに'\0'を格納しても、GlobalSize()いっぱいまで
    拾ってくれるアプリケーションはほとんど存在しないような予感します。少なくともメモ帳は無視されました。
    むしろGlobalSize()は適当に余分をもって確保して、\0以下は切り捨てられることを前提としているアプリケーションが一般的とか。

     
  • maru

    maru - 2006-12-24

    Logged In: YES
    user_id=1480232
    Originator: YES

    詳しくはhttp://sakura.qp.land.to/?Develop%2F5に書きましたが
    今回の問題は '\0' をコピーペーストできるようにするだけでは
    解決しない部分のようです。

    簡単に言うと、CMemory::MemUnicodeToSJISのあたりをどのような変換仕様
    にしたら良いか、という話になります。

    現状で、クリップボードにU+00A0が入っているとして
    CF_UNICODETEXTを取得 > CMemory::MemUnicodeToSJISでSJISに変換 > CMemory::MemSJISToUnicodeで元に戻す
    の順で実行すると、値は次のように変化します。
    U+00A0 > 0xA0 0x00 > U+0A00 U+0000

    問題点
    ・0xA0自体はサクラエディタで問題なく扱えるデータなのに、Unicode(U+00A0)との相互変換ができない
    ・CF_TEXTを利用するアプリケーションと動作が異なる
    ・CF_UNICODETEXTを優先する動作はdev:3934のあたりの都合によるため、変更はむずかしい
    ・wctombも意外と微妙
    ・CMemory::MemSJISToUnicodeでmbtowcが変換に失敗したときの救済処理がビッグエンディアンを出力している
    ・CEditView::MyGetClipboardDataからCMemory::MemUnicodeToSJISを呼び出すのもあまり美しくない。(CMemory::UnicodeToSJISを経由すべきだろうから)
    ・GlobalSize()によるサイズをクリップボードのテキストサイズとして問題ないか
    などです。

    全部を解決するのは仕様上困難と思われ、対応可能な範囲内で妥当な内容のみ修正したいと思います。
    ところで、テキストデータでクリップボードに'\0'を格納しても、GlobalSize()いっぱいまで
    拾ってくれるアプリケーションはほとんど存在しないような予感します。少なくともメモ帳は無視されました。
    むしろGlobalSize()は適当に余分をもって確保して、\0以下は切り捨てられることを前提としているアプリケーションが一般的とか。

     
  • Nobody/Anonymous

    Logged In: NO

    '\0' 文字もクリップボードに貼り付けられるよう変更を加える…とか.
    できるのかな;; -- rastiv? 2006-12-25 (月) 12:57:15

    当然GetもSetもできるようにするという意味ですよね?そういうのも作ってある
    のですが,気になる点が2つあります.Getの場合はGlobalSize()から得たサイズ
    を信頼してよいのか,Setの場合は\0を含むテキストを拾ってくれるアプリケーション
    が存在するのかどうか. -- maru 2006-12-26 (火) 01:57:02

    私,Win32系はまったく不慣れなので,MSDN の資料を見てみましたら,前者のような
    問題点に関する制限は記載されてませんです.後者に関しては確かに不安ですが,
    外部輸出専用クリップボードと内部アクセス専用のクリップボード(←概念的に)
    との間で'\0'文字を空白に変換するとか….的外れでしたらすみません;;
    -- rastiv? 2006-12-26 (火) 12:50:45

     
  • maru

    maru - 2007-01-01

    Logged In: YES
    user_id=1480232
    Originator: YES

    いろいろ検討しましたが、やはりCMemory::MemUnicodeToSJISとCMemory::MemSJISToUnicodeの
    動作仕様を変更するのが一番妥当な気がします。

    以下に、今回の問題の評価・検討結果をまとめました。

    ■発生条件
    SJISに変換できないUnicode文字のうち、上位バイトまたは下位バイトいずれかが0x00の場合

    ■発生場所
    1.外部アプリケーションからクリップボード経由でコピーペースト または
    2.外部アプリケーションへクリップボード経由でコピーペースト

    ■被害対象ユーザ
    1.編集機能が貧弱な外部アプリケーション(例えばExcel)からクリップボード経由で
      サクラエディタを作業スペースに利用しているユーザ
    2.HTML専用エディタなどとサクラエディタを併用してHTML系ドキュメントを編集するユーザ

    ■内容
    知らないうちにテキストデータの一部が欠落(切り捨て)する可能性がある。
    (ただし文字化け発生は、あらかじめユーザが認知しているものとする)
    今後、Unicode固有文字の使用が一般化してくれば、被害拡大。

    ■原因
    現在のMemUnicodeToSJISの仕様は、変換失敗文字は下位バイト・上位バイトをcharに
    そのままコピーしていますが、これをさらにMemSJISToUnicodeで処理した場合に、
    変換失敗文字が元のUnicodeテキストに戻らないことを保証する処理になっている。
    これは、charに格納されている値がバイナリなど非SJISを含んでいたのか、Unicodeからの変換に失敗した
    「そのままコピー」なのか、MemSJISToUnicodeでは区別できないため、「そのままコピー」された部分
    へのリカバリを行っていないことによる。

    ■仕様案
    現行仕様:そのままコピー+リカバリ無し
    動作内容:変換失敗文字は元に戻らないことを保証しつつ、クリップボードでのやり取りでは
         切り捨てが発生するかもしれない

    変更案1:変換失敗文字はクエスチョンマーク0x3Fに変換する、つまりwctombまかせ
    動作内容:変換失敗文字は元に戻らないことを保証しつつ、クリップボードとのやり取りでは
         切り捨ては発生しない

    変更案2:そのままコピー+変換失敗文字を判別するフラグを付加したCMemoryに変更+変換失敗文字のリカバリ処理追加
    動作内容:変換失敗文字はでも元に戻ることを保証する

    ■提案内容
    理想は変更案2ですが、パフォーマンスへの影響も心配なので、変更案1が無難な気がします。
    いずれも影響範囲が見えにくいので、十分な配慮が必要かと思います。

     
  • maru

    maru - 2007-01-01

    CMemory::UnicodeToSJIS経由に変更したもの

     
  • maru

    maru - 2007-01-01

    Logged In: YES
    user_id=1480232
    Originator: YES

    PasteUnicodeTextIncludeNull02.patchは '\0'をGet/Set
    するパッチで2006/12/25あたりの話題のものです。

    PasteUnicode_wctombForce.patchは、CMemory::MemUnicodeToSJIS
    での変換にて、変換処理をすべてwctombにおまかせのものです。
    File Added: PasteUnicodeTextIncludeNull02.patch

     
  • maru

    maru - 2007-01-01

    Logged In: YES
    user_id=1480232
    Originator: YES

    File Added: PasteUnicode_wctombForce.patch

     
  • maru

    maru - 2007-01-01

    CMemoryde

     
  • Nobody/Anonymous

    Logged In: NO

    まだパッチを試していないので、恐れ入りながらコメント。
    CMemory::MemUnicodeToSJIS と CMemory::MemSJISToUnicode の動作仕様変更案についてですけれど…

    現行仕様:そのままコピー+リカバリ無し
    動作内容:変換失敗文字は元に戻らないことを保証しつつ、クリップボードでのやり取りでは
         切り捨てが発生するかもしれない

    変更案1:変換失敗文字はクエスチョンマーク0x3Fに変換する、つまりwctombまかせ
    動作内容:変換失敗文字は元に戻らないことを保証しつつ、クリップボードとのやり取りでは
         切り捨ては発生しない

    変更案2:そのままコピー+変換失敗文字を判別するフラグを付加したCMemoryに変更+変換失敗文字のリカバリ処理追加
    動作内容:変換失敗文字でも元に戻ることを保証する

    変更案1をそのまま適用すると、文字化け修復手段として備わっている
    とおもわれる選択範囲を文字コード変換、みたいな機能が使えなくなってしまう恐れがあります。

    どの道大変するのなら、やはり変更案2を試みるか、
    またはみくさんが過去に提案なされてた、
    「クリップボードを選択して張り付け」機能を地道に考えていくほうが、
    いいのではないかと思われます。

     
  • maru

    maru - 2007-01-14

    クリップボードデータの変換では変換失敗文字'?'を許可

     
  • maru

    maru - 2007-01-14

    Logged In: YES
    user_id=1480232
    Originator: YES

    どなたか分かりませんが、コメントありがとうございます。

    変更案1をそのまま適用すると、文字化け修復手段として備わっている
    とおもわれる選択範囲を文字コード変換、みたいな機能が使えなくなってしまう恐れがあります。

    まさにその部分の問題なのです。
    ソースコードを見る限り、現状すでにwctombで対応できない文字はその '修復手段' が
    全く動作しないように見えるのです。というか、対策不可能な感じです。
    また、D&Dではwctombと同じ結果ですので、統一されてなくて不自然な感じもします。
    どうせ破壊されるなら、wctomb任せの方がまだマシじゃないか、と思ったわけです。

    と、ここまで書いて変更案3を思いつきました。
    変更案3:クリップボードデータの変換時のみ、wctomb任せ

    これで、現状のCMemory::MemUnicodeToSJIS にほとんど影響を与えることなく
    D&Dとクリップボードの結果を統一でき、当初の目的である切り捨て防止もできます。

    AllowFailureLetterFromCF_UNICODETEXT.patch
    File Added: AllowFailureLetterFromCF_UNICODETEXT.patch

     
  • R.T.H.

    R.T.H. - 2007-01-28

    Logged In: YES
    user_id=1439568
    Originator: NO

    nobody で投稿してしまった者です(f^^
    すみませんでした。

    クリップボードデータの変換時のみ、wctomb任せ
    AllowFailureLetterFromCF_UNICODETEXT.patch

    パッチ拝見しました。

    サクラエディタ内部で切り貼りする間は、
    その変換に失敗しているバイナリデータを
    どうにか保持できるように作り変えたとしても、
    それをクリップボード経由で外部ソフトへ持っていく場合は、
    maru さんの調べによれば、どうやっても無理なんですね・・・。

    CMemory に格納される任意データの表現方法と
    絡み合わせながら考えたんですけれど、
    バイナリデータを16進数のアスキー文字列で表して
    クリップボードにコピー、なんていう選択肢も残ってそうなんです。
    そちらについても検討されてみてはいかがでしょうか。

     
  • maru

    maru - 2007-02-04

    Logged In: YES
    user_id=1480232
    Originator: YES

    それをクリップボード経由で外部ソフトへ持っていく場合は、
    maruさんの調べによれば、どうやっても無理なんですね・・・。

    現在のUnicode→SJIS変換状況を整理すると下の1~5に分類されます。とりあえずサロゲートは無視します。

    1.SJISに可逆変換可能なもの
    2.SJISに不可逆変換のみ可能なもの(U+00C0など)
    3.SJISに変換できずに、Unicodeの上位バイトと下位バイトを並べると、なんらかのSJISマルチバイト文字に当てはまる(U+809Cなど)
    4.SJISに変換できずに、Unicodeの上位バイトと下位バイトのどちらか一方、またはそれぞれがASCII文字になっている(U+4E30など)
    5.SJISに変換できずに、SJIS文字にも当てはまらない(U+7FFAなど)

    このうち2については妥協でOKとしても、3と4はSJISに変換した時点で、ある意味文字化けした状況と同等です。

    さらに、こうした背景で5のケースでは、もう一度Unicodeに戻す場合に選択肢は2つあります。
    (1)すべての文字を、バイナリを含むSJISだと仮定して機械的にUnicodeに変換する
    (2)バイナリ部分は変換失敗文字と仮定して何もしない
    U+7FFAをSJIS→Unicode→SJISした場合に(1)の結果は[U+00FA,U+007F]、(2)の結果は[U+7FFA]ですが
    現状はどちらでもない[U+FA00,U+7F00]になっています。

    ちなみにクリップボードでデータが途切れるのは(1)の場合と現状の場合ですが、これはどちらかというと
    副次的な問題であり、あまり重要ではありません。

    今回はこの5のケースだけを問題に取り上げておりますが、実際には3~4のケースが多数を占めるのではないかと思われます。
    BBSで発言されている「"Unicode"をサポートするには」あたりの経過に思わず期待したくなります…。

    バイナリデータを16進数のアスキー文字列で表して
    クリップボードにコピー、なんていう選択肢も残ってそうなんです。
    どういう方法なのか、もう少し具体的に説明いただけますか。

     
  • R.T.H.

    R.T.H. - 2007-02-05

    Logged In: YES
    user_id=1439568
    Originator: NO

    バイナリデータを16進数のアスキー文字列で表して
    クリップボードにコピー、なんていう選択肢も残ってそうなんです。
    どういう方法なのか、もう少し具体的に説明いただけますか。

    えっと。今取り上げられている問題を、
    単純に文字コード変換に失敗した際のフォローの問題だと考えます。
    たとえば、CMemory::MemUnicodeToSJIS 処理中、
    Unicode 文字が SJIS 文字に変換できなかったとき、
    '?'マークに変換する方法をとるのが、maru さんが提案なさった
    フォローその1でした・・・よね(汗 (間違っていましたらご指摘ください。)
    けれども、改行などのデータの差異を正確に表現しようとする
    サクラエディタとしては、どうしてもデータを復元できる状態で
    表したいということで、不正値 0xFF(ワイド文字なら 0xFFFF)を
    第一バイト(ワイド文字なら第一ワード)とする、
    1バイトを表す仮の文字を内部的に定義する方法を思いつきました。
    仮の文字と値の対応は、以下のような感じです。

    0xFF 0x00 - 0x00
    0xFF 0x01 - 0x01
    0xFF 0x02 - 0x02
    : :
    : :
    0xFF 0xFE - 0xFE
    0xFF 0xFE 0xFE - 0xFF // ワイド文字の場合、ここの対応は 0xFFFF 0x00FF - 0x00FF

    しかしこの形式では一般的なクリップボードにコピーできないので、
    このデータをテキストで表現する方法として、
    アスキー文字 0 から 9 と A から F の文字を使った
    16進数表記をつかうといいのではないかと思った次第です。

    ・・・物がまだできてないのでアレなんですが(^^;
    まとめると、

    いろいろ絡んでる問題を、
     「クリップボードにコピーできない任意値をテキストでどう表現するか」
     だけに的を絞って、とりあえず対処しよう。
     ただ、一律'?'マークで表現するのはあまりにあっけないので、
     16進数表記ではどうか。
     また、残るデータのリカバリ機能については、
     根本的な問題として、別途対処する。

    ・・・みたいな感じです。

     
  • Nobody/Anonymous

    Logged In: NO

    ラスティブです。

    時期的に、サクラエディタ1.x系の終焉に近づいていると感じる
    今日この頃、このバグを放置しておくわけには行かないような
    気がするので、maruさんの考えで作成したパッチをコミットに向けて
    転がしていっていただければと思います。

    自分がパッチ作成の進行を止めておきながら、
    長期にわたって無反応であったことをお詫びします。

     
  • maru

    maru - 2007-11-02

    Logged In: YES
    user_id=1480232
    Originator: YES

    ながらく放置ですいません。

    この件はUnicode版の評価でUchiさんがしている
    http://mofmof.nsf.tc/soft/sakura.php
    の36項と本質的には同じ問題です。

    SJISの読み込み時、コードが 0xa0,0xfd,0xfe,0xff
    の文字が 0xa000,0xfd00,0xfe00,0xff00 になる

    その場しのぎのイレギュラーなオプションを
    安易に追加すると、その機能を削除するのは
    難しいことと、Unicode対応に伴って自然収束
    するだろうとの判断から、敢えて保留にしていました。

    未解決に見えて紛らわしいので、Closeします。

     

Log in to post a comment.

MongoDB Logo MongoDB